Last active
September 9, 2020 05:51
-
-
Save stathissideris/7eb2d14990d0b23f8edbee53dbb7bc21 to your computer and use it in GitHub Desktop.
An attempt to use Datascript for state management in a Swing app (no React)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns not-posh | |
(:require [clojure.string :as str] | |
[clojure.data :as data] | |
[datascript.core :as d] | |
[clojure.set :as set] | |
[seesaw.core :as ss])) | |
(defn- diff [a b] | |
;;TODO make diff ignore :swing/component key but include it in result | |
(let [[removed added] (data/diff a b) | |
removed (zipmap (map :db/id removed) removed) | |
added (zipmap (map :db/id added) added) | |
common-keys (set/intersection (set (keys removed)) | |
(set (keys added)))] | |
{:removed (vals (apply dissoc removed common-keys)) | |
:added (vals (apply dissoc added common-keys)) | |
:edited (not-empty (map #(hash-map :before (get removed %) :after (get added %)) common-keys))})) | |
(defn listen! [conn k query fun] | |
(d/listen! | |
conn k | |
(fn [{:keys [db-before db-after]}] | |
(let [before (d/q query db-before) | |
after (d/q query db-after) | |
the-diff (diff before after) | |
datoms (when (some not-empty (vals the-diff)) | |
(fun db-before db-after the-diff))] | |
(when-not (empty? datoms) | |
(d/transact! conn datoms)))))) ;;TODO infinite recursion fun! | |
(defn assoc-component [db {:keys [id] :as record}] | |
(assoc record :component | |
(d/q `[:find ?c . :where [~id :swing/component ?c]] db))) | |
(listen! | |
conn ::windows | |
;;the query HAS to return :db/id for editing diff to work | |
;;optional :swing/component is ignored in diff (TODO) | |
'[:find ?d ?filename ?edited ?component | |
:keys db/id filename edited swing/component | |
:where | |
[?d :doc/filename ?filename] | |
[?d :doc/edited ?edited] | |
[(get-else $ ?d :swing/component :none) ?component]] | |
(fn [db-before db-after {:keys [removed added edited] :as diffs}] | |
(prn 'diffs diffs) | |
;; close windows | |
(doseq [{:keys [swing/component]} removed] | |
(ss/dispose! component)) | |
;; rename windows | |
(let [edited (map :after edited)] | |
(doseq [{:keys [filename edited swing/component]} edited] | |
(ss/invoke-later (ss/config! component :title (str filename (when edited "*")))))) | |
;; open new windows and register the components in the state by returning transact! vectors | |
(for [{:keys [db/id filename edited]} added] | |
[:db/add id :swing/component (doto (ss/frame :title (str filename (when edited "*")) | |
:content (ss/label :text filename) | |
:on-close :dispose) | |
(ss/pack!) | |
(ss/show!))]))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment