Clojure for Desktop UI Design Application

1,600 views
Skip to first unread message

MS

unread,
Jan 12, 2015, 1:53:07 PM1/12/15
to clo...@googlegroups.com
(Cross-posted on StackOverflow)

I'm trying to design a desktop UI for schematics, layout, drawing stuff.  Just looking for high level advice from actual software designers.

Assuming an in-memory "database", (clojure map of arbitrary depth for all user data, and possibly another one for application preferences, etc.), I'm examining how to do the model-view-controller thing on these, where the data may be rendered *and modified by* any one or more of:

 1. A standalone text field that shows a single parameter, such as box width.
 2. An "inspector" type of view that shows multiple parameters of a selected object, such as box width, height, color, checkboxes, etc.
 3. A table/spreadsheet type of view that shows multiple parameters of multiple objects, potentially the whole database
 4. A graphical rendering of the whole thing, such as both schematic and layout view.

Modifying any one of these should show up immediately in every other active view, both text and graphical, not after clicking "ok"... so no modal boxes allowed.  If for some reason the table view, an inspector view, and a graphical rendering are all in view, dragging the corner of the box graphically should immediately show up in the text, etc.

The platform in question is JavaFX, but I'd like a clean separation between UI and everything else, so I want to avoid `bind`ing in the JFX sense, as that ties my design data very tightly to JFX Properties, increases the graininess of the model, and forces me to work outside the standard clojure functions for dealing with data, and/or deal heavily with the whole `getValue`/`setValue` world.

I'm still assuming at least *some* statefulness/mutability, and the use of built-in Clojure functionality such as the ability to `add-watch` on an atom/var/ref and let the runtime signal dependent functions.

Platform-specific interaction will rest tightly with the actual UI, such as reifying `ActionListener`s, and dealing with `ObservableValue`s etc., and will attempt to minimize the reliance on things like JavaFX `Property` for actual application data.  I'm not entertaining FRP for this.  

I don't mind too much extending JFX interfaces or making up my own protocols to use application-specific `defrecord`s, but I'd prefer for the application data to remain as straight Clojure data, unsullied by the platform.

The question is how to set this all up, with closest adherence to the immutable model and minimal (or well-bounded) dependence on JFX.  I see a few options:

 1. Fine-grain: Each parameter value/primitive (ie Long, Double, Boolean, or String) is an atom, and each view which can modify the value "reaches in" as far as it needs to in the database to change the value.  This could suck as there could potentially be thousands of individual values (for example points on a hand-drawn curve), and will require lots of `(deref...)` junk.  I believe this is how JFX would want to do this, with giant arrays of Properties at the leaf nodes, etc., which feels bloated.  With this approach it doesn't seem much better than just coding it up in Java/C++.
 2. Medium-grain: Each object/record in the database is an atom of a Clojure map.  The entire map is replaced when any one of its values changes.  Fewer total atoms to deal with, and allows for example long arrays of straight-up numbers for various things.  But this gets complicated when some objects in the database require more nesting than others.
 3. Coarse-grain: There is just one atom: the database.  Any time anything changes, the entire database is replaced, and every view needs to re-render its particular portion.  This feels a bit like using a hammer to swat a fly, and a naive implementation would require everything to re-render all the time.  But I still think this is the best trade off, as any primitive has a clear access path from the root node, whether it is accessed on a per-primitive level or per-record level.

I also need the ability for one data template to be instantiated many times.  So for example if the user changes a symbol or shape which is used in multiple places, a single edit will apply everywhere.  I believe this also requires some type of "pointer"-like behavior.  I think I can store a atom to the model, then instantiate as needed, and it can work in any of the above grain models.

Any other approaches?  Is trying to do a GUI editor-like tool in a functional language just stupid?
Thanks

Colin Yates

unread,
Jan 13, 2015, 10:15:26 AM1/13/15
to clo...@googlegroups.com
Wow, there is a lot to deal with :), so let me throw out some ideas:
 - have you considered building a web-app instead of a desktop app? If so, have a look at one of the react based languages (om or reagent would be my choice). Alternatively take a look at other http://en.wikipedia.org/wiki/Functional_reactive_programming libraries. 

It is a different way of working, but its programming model restricts you in a way that removes many problems (if you see what I mean).

Also, I would be reaching for an in-memory database (assuming a server isn't involved) about now, datatomic would be the obvious choice.

I don't think what you are trying to do is stupid, I do think you might want to do some thought experiments about different architectures and paradigms (specifically FRP related paradigms).

Oh, and have a quick scan through http://swannodette.github.io/, there are a few "mind-changing" posts.

Timothy Baldridge

unread,
Jan 13, 2015, 11:05:40 AM1/13/15
to clo...@googlegroups.com
I've long thought that the Clojure world needs a JavaFX/React hybrid. JavaFX2's API is extremely consistent, making it quite easy to program against, but yes it still requires bindings and in-place mutation. 

However a React-like diff-ing engine on it would be quite impressive. But now you're into the fun land of writing a library in order to write your app. 

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
“One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.”
(Robert Firth)

zirkonit

unread,
Jan 13, 2015, 11:19:43 AM1/13/15
to clo...@googlegroups.com
What about node-webkit + Clojurescript? I think it would be ideal environment for desktop GUI?

MS

unread,
Jan 13, 2015, 11:21:24 AM1/13/15
to clo...@googlegroups.com
Hi, thanks for the response.  Yes I've thought about a web-based platform.  There are tools like LightTable and UpVerter which are inspiring, and I understand the V8 javascript engine renders stuff pretty quickly.  Unfortunately that would require getting up to speed on yet another way of thinking about things, clojurescript, etc.  I'm kind of still stuck in the 90's and I have only so much brain power/attention/time available. :)  I'll take a look at datomic.  There are so many libraries and various tools for asynchronous frp javascript web based back-end server json immutable reactive things I really can't keep up with all the cool kids.  

MS

unread,
Jan 13, 2015, 11:28:21 AM1/13/15
to clo...@googlegroups.com
If I come up with anything that might usefully tie Clojure data structures to JavaFX UI elements in a clean way, I may release it on github.  For now it's just one or two .clj files with all my random monkey-coding, using lots of half-examples from various sources, which is pretty much how I learn.  I played around with Seesaw (Swing-based) for a little bit, but it started to get a little too abstract for me, and anyway, as a friend of mine recently said, Swing looks like ass, even if you set it to look like the native platform, and I need my app to be "rich", etc.  There's also a certain part of me that feels that "all these" asynchronous libraries out there (react? core.async?  I really don't know what I'm talking about [I'm a hardware engineer]), add a lot of overhead with threads, etc., and I may be wrong, but it feels like there would need to be fewer layers between clicking the mouse and having something show up.  I believe any cad/drawing/design tool needs to be as reactive and real-time as any game, so max 16ms latency.  I'm not saying I have any evidence these libraries are slow... I'm just saying it feels like overkill when I'm not writing a big web server or anything.  I'm probably wrong.

Colin Yates

unread,
Jan 13, 2015, 11:50:44 AM1/13/15
to clo...@googlegroups.com
My evolution of Java UI was swing>JSP>struts>JSF>velocity then onto
JavaScript/ExtJS. My instinct now when I hear the words "Java" and
"UI" is to run a mile :).

I haven't looked at JavaFX (I think I had bailed before that appeared).
> You received this message because you are subscribed to a topic in the
> Google Groups "Clojure" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/clojure/Ut-HkNTqRUo/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to

Colin Yates

unread,
Jan 13, 2015, 11:52:39 AM1/13/15
to clo...@googlegroups.com
One lesson I would share is that things are usually much quicker than
we expect. Always prove it is too slow before believing your
intuition.
> You received this message because you are subscribed to a topic in the
> Google Groups "Clojure" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/clojure/Ut-HkNTqRUo/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to

Gary Trakhman

unread,
Jan 13, 2015, 12:02:55 PM1/13/15
to clo...@googlegroups.com
You made the analogy to games/graphics, React model treats the DOM akin to a graphics buffer, and they themselves present it as similar to the doom3 architecture.  In practice, it feels a lot like a scene graph, with the update/render methods on every component.

I don't know how easy it is to fit javafx into this, but it works out with the DOM pretty well.  If JavaFX can be described as a renderer of a static data structure, then you should be able to do the same kind of tree-diffing optimizations that React does to minimize what needs to be redrawn, and to present a functional/data interface.


> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "Clojure" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/clojure/Ut-HkNTqRUo/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to

> For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscribe@googlegroups.com.
Message has been deleted

Fluid Dynamics

unread,
Jan 13, 2015, 12:48:44 PM1/13/15
to clo...@googlegroups.com
On Tuesday, January 13, 2015 at 10:15:26 AM UTC-5, Colin Yates wrote:
Wow, there is a lot to deal with :), so let me throw out some ideas:
 - have you considered building a web-app instead of a desktop app? If so, have a look at one of the react based languages (om or reagent would be my choice). Alternatively take a look at other http://en.wikipedia.org/wiki/Functional_reactive_programming libraries. 

It is a different way of working, but its programming model restricts you in a way that removes many problems (if you see what I mean).

Also, I would be reaching for an in-memory database (assuming a server isn't involved) about now, datatomic would be the obvious choice.

Unless you want to go open source...

Mike Haney

unread,
Jan 13, 2015, 1:16:57 PM1/13/15
to clo...@googlegroups.com
My evolution is similar to Colin's, with more SWT than Swing.  And I understand where you're coming from - did Java for 15 years and C++ before that.  I didn't even really learn about functional programming until about 3 years ago, and after an aborted dive into learning Scala I switched to Clojure 18 months ago and haven't looked back.

Anyway, given what I know today If I had to write a desktop GUI, my first instinct would be Clojurescript+node-webkit.

There's not as much to learn as you might think.  It sounds like you already know Clojure, so Clojurescript isn't a big leap.  Core.async is not, but by no means a requirement - you can safely ignore it for now and only reach for it if it solves a particular problem you are having.  For the database, there is Datascript which is basically Datomic in the browser.  This would give you a very capable embedded database that you can simply serialize to a file to store your "document" in a desktop app.  

Coming from a mostly server background, I found the React model very familiar and easy to pick up.  You get a request, query the database, and render a template.  It looks very different in React, but conceptually it's the same thing as PHP or Spring MVC or whatever.  You also gain access to a huge number of JS widgets for just about anything you can imagine, from fancy input controls to graphs and charts and even 3d rendering.  

Here's a simple model you can start with and build on as-needed - use Datascript as your "source of truth" for your data, and all your event handlers and other application logic simply transacts against this DB.  Your views simply query the DB to construct their data.  All that's left is triggering when the view refreshes to reflect changes in the DB, and that will depend on which React wrapper library you are using.  

In my experience, to integrate with Datascript the easiest to hardest choices are: Rum, Quiescent, Reagent, Om.  I've recently switched to Rum (by the same guy who wrote Datascript) and it's dead simple - like 3 lines of code, done!  But Rum is very new and fairly low level, so it might not be the easiest to start with.  For overall ease of use, Reagent is a great choice although the integration with Datascript is a bit more work.  If you're interested, I can go into more detail on how you might integrate Datascript with a given library.

Jason Lewis

unread,
Jan 13, 2015, 1:41:34 PM1/13/15
to clo...@googlegroups.com
If you're looking for functional reactive programming in Clojure (rather than going web-based), there's a great library for Clojure bindings to RxJava: https://github.com/ReactiveX/RxClojure

Jason Lewis

vox      410.428.0253
twitter  @canweriotnow

--

Christopher Small

unread,
Jan 13, 2015, 2:04:57 PM1/13/15
to clo...@googlegroups.com
Something else to consider...

If you really want to avoid doing a web app with all the complexity of server code, client code, html, css, database, etc, then you might want to look into [quil](https://github.com/quil/quil). It's a clojure wrapper of the processing library for doing data visualizations, code art, and even small GUI applications. It's not something you typically see used for large-scale applications, but it's quite fun and is actually fairly impressive considering it's scope.

On the other hand, while the web app route may feel a bit overwhelming, it really is worth learning. Once you program web, you can deliver to any platform. It's ubiquitous. And once you get the hang of it, the paradigm isn't really all that challenging. But up to you obviously.

Good luck

Gary Trakhman

unread,
Jan 13, 2015, 2:46:29 PM1/13/15
to clo...@googlegroups.com
On Tue Jan 13 2015 at 2:05:03 PM Christopher Small <metas...@gmail.com> wrote:
On the other hand, while the web app route may feel a bit overwhelming, it really is worth learning. Once you program web, you can deliver to any platform. It's ubiquitous. And once you get the hang of it, the paradigm isn't really all that challenging. But up to you obviously.

 
This rationale is the basis for my last 1.5 years of extra-work effort.  Good luck :-).

Coming from clojure, React really made investing in the web seem sane and worthwhile by offering composable abstraction.  I still think it's a good idea to learn web tech, but it was kind of a frustrating slog.

Another really helpful piece of 'tech' that fits with clojure philosophies is http://suitcss.github.io/ 

I think that plus React are great starting points.

Timothy Baldridge

unread,
Jan 13, 2015, 3:09:46 PM1/13/15
to clo...@googlegroups.com
Before coming to Clojure I did 2 years of work on WPF/Silverlight apps, and let me say what those platforms offer blows the web stuff out of the water. Yes it's not cross-platform, but the ability to describe a layout with data is unparalleled in the web world. I could sit down, and have a UI to a CRUD app in half a day. No CSS, no DOM elements to force into a layout I wanted, etc. Ask anyone who's worked with WPF and they'll tell you "yep it's based on mutability, but writing a UI is really easy".

JavaFX comes close to this, but I'd like to use pure data to interact with it. I did some work on that in the past, and came up with something that was pretty usable, but I think a React approach could take it even further. Anyways, the results of my work allowed you to create JavaFX interfaces like this:

{:type   :border-pane
                     :center {:type     :group
                              :children [{:type    :circle
                                          :radius  (planet-sizes size)
                                          :centerY (/ (planet-sizes size) 2)
                                          :centerX 0}]}
                     :bottom {:type       :stack-pane
                              :maxHeight  110
                              :prefHeight 110
                              :children   [{:type :pie-chart
                                            :data (map
                                                    (fn [{percent :planet.biome/percentage
                                                          type    :planet.biome/type}]
                                                      (slide/build-item {:type  :pie-chart-data
                                                                         :name  (str type)
                                                                         :value percent}))
                                                    (:planet/biomes planet))}]}}


Notice how you don't have to muck with all the junk found in the browser, you just describe an panel, say what you want to put where (center, bottom, etc). and the layout engine takes care of the rest. And this entire thing is GPU accelerated so drawing of the GUI is pretty fast. 

The web side of things has a place, but it's also mired in decades of legacy, that's stuff you don't find in modern UI toolkits like JavaFX, QT and WPF. 

Timothy

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

blake

unread,
Jan 13, 2015, 4:18:44 PM1/13/15
to clo...@googlegroups.com
Yeah, Adobe Flex can do that, too, with all the same caveats.

TP

unread,
Jan 13, 2015, 8:12:17 PM1/13/15
to clo...@googlegroups.com

On Tue, Jan 13, 2015 at 10:16 AM, Mike Haney <txmik...@gmail.com> wrote:
Anyway, given what I know today If I had to write a desktop GUI, my first instinct would be Clojurescript+node-webkit

Since I'm still investigating Clojure, my first instinct when writing a desktop GUI --- similar to what Timothy Baldridge mentions --- is to use C# + WPF. In particular I really like the Model-View-ViewModel architecture enabled by the fancy data binding that XAML/WPF can do. And the relatively new Assisticant [1] [2] seems to make that even easier (though I've haven't actually used it yet).

Given that I'm more comfortable with .NET... for functional programming I've started to use F# for "real work" (as opposed to toy apps/solving koans while learning Clojure). While you can write WPF apps with F# there is still some work to do. FsXaml [3] [4] is trying to address this need. And while I'm still learning, it seems like F# can do React-like "Functional Reactive Programming" [5]. Of course ClojureCLR [6] is also an alternative for .NET-centric types but I only looked at it briefly.

I spent some time trying to grok LightTable, but the Clojure/ClojureScript/Javascript/leiningen/Google Closure compiler/JVM/node-webkit combo caused me to give up for now. It didn't help that Windows support tends to be an afterthought. BTW LightTable is seriously considering jettisoning node-webkit and switching to the github Atom shell instead [7].

[1] http://assisticant.net/

[2] http://www.pluralsight.com/courses/clean-view-models-assisticant

[3] https://github.com/fsprojects/FsXaml

[4] Reed Copsey: New libraries for Client Side development in F#
    https://www.youtube.com/watch?v=z6R85_X2ivE

[5] http://fsharpforfunandprofit.com/posts/concurrency-reactive/

[6] https://github.com/clojure/clojure-clr

[7] https://groups.google.com/forum/#!searchin/light-table-discussion/atom$20shell$20chris$20granger

Mikera

unread,
Jan 13, 2015, 8:14:50 PM1/13/15
to clo...@googlegroups.com
I'd be pretty interested in this too. Though not quite enough to write it myself (I've made "good enough" interfaces with Swing interop).

The thought occurs that there may be quite a bit of common code that could be shared with respect to diffing / cursors etc. that would work equally well for Om, JavaFX2, maybe also some OpenGL rendering. This similarity might even be exploited to build re-targetable GUI code. OK I'll stop speculating now....

Colin Fleming

unread,
Jan 13, 2015, 8:36:36 PM1/13/15
to clo...@googlegroups.com
On 14 January 2015 at 05:50, Colin Yates <colin...@gmail.com> wrote:
My evolution of Java UI was swing>JSP>struts>JSF>velocity then onto
JavaScript/ExtJS. My instinct now when I hear the words "Java" and
"UI" is to run a mile :).

This is where I point out that you're currently using a Swing app every day :-)

Colin Yates

unread,
Jan 13, 2015, 11:28:24 PM1/13/15
to clo...@googlegroups.com

IntelliJ is swing! Well, knock me other with a feather :). Still wouldn't want to go anywhere near building a Swing app though :).

juan.facorro

unread,
Jan 18, 2015, 3:08:39 PM1/18/15
to clo...@googlegroups.com
Hi Timothy,

I took an extremely similar approach in this project using Swing as the underlying UI toolkit. Components can be described using a hiccup like syntax, although they are actually represented as maps in the end. Since the UI is mutable by nature the root component (an immutable map) is held in an atom. 

Before building this abstraction I considered implementing something like the React approach, but at the time it seemed like a lot of work and I was not convinced it could actually work since I hadn't heard of React back then. I think pursuing the same approach with a desktop UI toolkit would be an interesting project.

Juan

dilettan...@live.com

unread,
Jun 2, 2015, 3:16:17 PM6/2/15
to clo...@googlegroups.com
I'm a newbie in the JVM/Clojure world, and a past user of C#/WPF.  I had similar questions for a JVM desktop application, and came upon this interesting project: http://open-dolphin.org/dolphin_website/Home.html.  The notion here is that you mutate very simple, generic presentation models at the back end, and all changes are instantly communicated to clients; changes at the UI are automatically sent to the server-side presentation model.  You can listen for changes in the back end presentation model, and register command handlers.  The documentation claims, "You get a full reactive event-driven programming model in the normally request-response oriented Java enterprise world."  At the front end, the presentation model is technology-agnostic: you can bind to JavaFX, or choose another method.

I thought that this might serve -- with a wrapper of some sort -- as a bridge between Clojure's immutable models and whatever mutable world you'd have to interact with at the UI.  Caveat: haven't really used it yet, and don't know whether it'll work smoothly.  The Canoo guys have released some interested demos and presentations which are linked to at the website.

  Vikram


Efrain Bergillos

unread,
Jun 27, 2015, 10:04:26 AM6/27/15
to clo...@googlegroups.com

I have been working on a desktop App for the last few months and I have not got many problems with the architecture and isolation of the views.


In my young blog, I have few posts of how to set up and launch the JavaFX App.


I also have a MVVM and the conventions of how to compose each layer.


In regard to the events, I have also written an Pub-Sub event bus inspired by Timothy Baldridge using core.async.


There is a wrapper called clojurefx by Zilti that helps you binding properties of the visual components to atoms. He is refactoring this library in his Bitbucket repo. I am using the one in GitHub.


You can also use the add-watch for listening to changes in the state or inferior layers, as you would do with an "addListener".


In regard to the cache or client database, I have a lack of knowledge on that. At the moment I have a very cheap bespoke solution using steveskeys, which use a couple of random access files to read and dump the nippy serialized objects from memory to disk and viceversa.

If you have a good solution for your client cache/database I would like to hear about it.


The idea of that cache, is giving some relief to the server on calls that you have previously done and have an offline capabilities to visualize an aggregated snapshot of your data. But when missing the cache, would just mean, doing few more REST calls to the server.


If you want more details about the MVVM desktop app, I can help you with that. I have 2500 lines plus the CSS. Ping me on twitter.

http://www.efrainbergillos.com/clojure/clojure-publishers-subscribers-and-mvvm/


Regards, Efrain



On Monday, 12 January 2015 18:53:07 UTC, MS wrote:
Reply all
Reply to author
Forward
0 new messages