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.



On Tuesday, January 13, 2015 at 10:21:24 AM UTC-6, MS wrote:
>
> 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.  
>
> On Tuesday, January 13, 2015 at 7:15:26 AM UTC-8, 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.
>>
>> 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.
>>
>> On Monday, 12 January 2015 18:53:07 UTC, MS wrote:
>>>
>>> (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
>>>
>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@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+unsubscr...@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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to