From bb46b8535ee5f0db7dca0ca0cb76e1c199c29f83 Mon Sep 17 00:00:00 2001 From: Kimo Knowles Date: Thu, 31 Oct 2024 22:09:40 +0100 Subject: [PATCH] [wip] --- src/re_com/nested_grid/util.cljc | 73 +++++++------ src/re_demo/nested_grid.cljs | 174 +++++++++++++++++++------------ 2 files changed, 145 insertions(+), 102 deletions(-) diff --git a/src/re_com/nested_grid/util.cljc b/src/re_com/nested_grid/util.cljc index a88ae55e..ab619ad2 100644 --- a/src/re_com/nested_grid/util.cljc +++ b/src/re_com/nested_grid/util.cljc @@ -90,32 +90,35 @@ (keyword? node) 20))) (defn walk-size [{:keys [window-start window-end tree size-cache]}] - (let [sum-size (volatile! 0) - level->space (volatile! {}) - windowed-paths (volatile! []) - windowed-sizes (volatile! []) - windowed-sums (volatile! []) - collect-space! (fn [level space] - (vswap! level->space - (fn [m] (cond-> m - (not (get m level)) (assoc level space))))) - collect-size! (fn [size] (vswap! windowed-sizes conj size)) - forget-size! #(vswap! windowed-sizes pop) - collect-sum! (fn [sum] (vswap! windowed-sums conj sum)) - forget-sum! #(vswap! windowed-sums pop) - collect-path! (fn [size] (vswap! windowed-paths conj size)) - forget-path! #(vswap! windowed-paths pop) - cache! (if-not size-cache - (constantly nil) - (fn [node size] (vswap! size-cache assoc node size))) - lookup (if-not size-cache - (constantly nil) - #(get @size-cache %)) - intersection? (if-not (and window-start window-end) - (constantly true) - (fn [[x1 x2]] - (and (<= x1 window-end) - (>= x2 window-start)))) + (let [sum-size (volatile! 0) + level->space (volatile! {}) + windowed-paths (volatile! []) + windowed-leaf-paths (volatile! []) + windowed-sizes (volatile! []) + windowed-sums (volatile! []) + collect-space! (fn [level space] + (vswap! level->space + (fn [m] (cond-> m + (not (get m level)) (assoc level space))))) + collect-size! (fn [size] (vswap! windowed-sizes conj size)) + forget-size! #(vswap! windowed-sizes pop) + collect-leaf-path! (fn [path] (vswap! windowed-leaf-paths conj path)) + forget-leaf-path! #(vswap! windowed-leaf-paths pop) + collect-sum! (fn [sum] (vswap! windowed-sums conj sum)) + forget-sum! #(vswap! windowed-sums pop) + collect-path! (fn [size] (vswap! windowed-paths conj size)) + forget-path! #(vswap! windowed-paths pop) + cache! (if-not size-cache + (constantly nil) + (fn [node size] (vswap! size-cache assoc node size))) + lookup (if-not size-cache + (constantly nil) + #(get @size-cache %)) + intersection? (if-not (and window-start window-end) + (constantly true) + (fn [[x1 x2]] + (and (<= x1 window-end) + (>= x2 window-start)))) walk (fn walk [path node & {:keys [collect-me?] :or {collect-me? true}}] (cond @@ -124,6 +127,8 @@ leaf-path (conj path node) level (count leaf-path) bounds [sum (+ sum leaf-size)]] + (when (intersection? bounds) + (collect-leaf-path! leaf-path)) (when (and (intersection? bounds) collect-me?) (collect-path! leaf-path) (collect-sum! sum) @@ -153,18 +158,20 @@ (collect-space! level sum) (do (forget-path!) + (forget-sum!) (forget-size!))) (when-not csize (cache! node total-size)) total-size)))))] (walk [] tree) - {:sum-size @sum-size - :level->space (into (sorted-map) @level->space) - :windowed-sums @windowed-sums - :windowed-paths @windowed-paths - :windowed-sizes @windowed-sizes - :window-start window-start - :window-end window-end})) + {:sum-size @sum-size + :level->space (into (sorted-map) @level->space) ;;TODO remove this. + :windowed-sums @windowed-sums + :windowed-paths @windowed-paths + :windowed-sizes @windowed-sizes + :windowed-leaf-paths @windowed-leaf-paths + :window-start window-start + :window-end window-end})) (def test-tree [:z [:g diff --git a/src/re_demo/nested_grid.cljs b/src/re_demo/nested_grid.cljs index f4ffbe99..3d131075 100644 --- a/src/re_demo/nested_grid.cljs +++ b/src/re_demo/nested_grid.cljs @@ -1033,7 +1033,7 @@ :position :relative :height sum-size}} [:div {:style {:position :fixed - :margin-left 20 + :margin-left 420 :display :grid :grid-template-rows (str/join " " (->> path-seq (map last) @@ -1043,13 +1043,13 @@ [:div {:style {:position :fixed :height window-size :width 220 - :margin-left "70px" + :margin-left "470px" :border-top "thick solid red" :border-bottom "thick solid red" :margin-top (* 2 @scroll-top) :background "rgba(0,0,1,0.2)"}} (str (* 2 @scroll-top))] - [:div {:style {:width 400 + [:div {:style {:width 600 :height (* sum-size (+ 1 window-ratio))}} (str sum-size)]] [:br] @@ -1060,15 +1060,21 @@ (into [(first v)] (map (fn [[a b]] (- b a)) (partition 2 1 v)))) +(def wx (r/reaction @scroll-left)) +(def ww (r/atom 100)) +(def wy (r/reaction @scroll-top)) +(def wh (r/atom 100)) + (defn new-nested-grid [{:keys [row-tree column-tree]}] (let [internal-row-tree (r/atom (u/deref-or-value row-tree)) internal-column-tree (r/atom (u/deref-or-value column-tree)) - wx (r/reaction @scroll-left) - ww (r/atom 50) - wy (r/reaction @scroll-top) - wh (r/atom 100) - row-traversal (r/reaction (ngu/walk-size {:tree @internal-row-tree :window-start (* @wy 2) :window-end (+ (* @wy 2) @wh)})) - column-traversal (r/reaction (ngu/walk-size {:tree @internal-column-tree}))] + + row-traversal (r/reaction (ngu/walk-size {:tree @internal-row-tree + :window-start (* 2 @wy) + :window-end (+ (* 2 @wy) @wh)})) + column-traversal (r/reaction (ngu/walk-size {:tree @internal-column-tree + :window-start @wx + :window-end (+ @wx @ww)}))] (r/create-class {:component-did-update #(let [[_ {:keys [row-tree column-tree]}] (r/argv %)] @@ -1084,55 +1090,79 @@ :grid-column-start (ngu/path->grid-line-name column-path)}}])}}] (u/deref-or-value row-tree) (u/deref-or-value column-tree) - (let [{row-space :level->space - row-height-total :sum-size - windowed-row-paths :windowed-paths} @row-traversal - {column-space :level->space - column-width-total :sum-size - windowed-column-paths :windowed-paths} @column-traversal - column-depth (count column-space) - column-header-heights (repeat column-depth column-header-height) - column-header-height-total (apply + column-header-heights) - row-depth (count row-space) - row-header-widths (repeat row-depth row-header-width) - row-header-width-total (apply + row-header-widths) - row-tokens (ngu/lazy-grid-tokens @row-traversal) - row-template (ngu/lazy-grid-template row-tokens) - row-spans (ngu/grid-spans row-tokens) - column-tokens (ngu/lazy-grid-tokens @column-traversal) - column-template (ngu/lazy-grid-template column-tokens) - spacer-container [:div {:style {:border "thin solid lightblue"}} "spacer"] - column-header-container [:div {:style {:border "thin solid lightblue"}} "column"] - row-header-container [:div {:style {:display :grid - :grid-template-rows row-template - :grid-template-columns (ngu/grid-template row-header-widths)}}] - row-header-cells (for [path windowed-row-paths] - [:div {:style {:grid-row-start (ngu/path->grid-line-name path) - :grid-row-end (str "span " (get row-spans path)) - :grid-column-start (count path) - :grid-column-end (str "span " (+ 1 (- row-depth (count path)))) - :border-top "thin solid green" - :border-left "thin solid green" - :overflow :hidden - :font-size 8}} - - (pr-str path)]) - main-container [:div - {:style {:flex "0 0 auto" - :display :grid - :grid-template-rows (ngu/grid-template [column-header-height-total row-height-total]) - :grid-template-columns (ngu/grid-template [row-header-width-total column-width-total])}}] - cell-grid-container [:div {:style {:display :grid - :grid-template-rows row-template - :grid-template-columns column-template}}] - cells (for [row-path windowed-row-paths - column-path windowed-column-paths] - (u/part cell {:row-path row-path :column-path column-path}))] - (conj main-container - spacer-container - column-header-container - (into row-header-container row-header-cells) - (into cell-grid-container cells))))}))) + (let [{row-space :level->space + row-height-total :sum-size + windowed-row-paths :windowed-paths + windowed-row-leaf-paths :windowed-leaf-paths} @row-traversal + {column-space :level->space + column-width-total :sum-size + windowed-column-paths :windowed-paths + windowed-column-leaf-paths :windowed-leaf-paths} @column-traversal + column-depth (count column-space) + column-header-heights (repeat column-depth column-header-height) + column-header-height-total (apply + column-header-heights) + row-depth (count row-space) + row-header-widths (repeat row-depth row-header-width) + row-header-width-total (apply + row-header-widths) + row-tokens (ngu/lazy-grid-tokens @row-traversal) + row-template (ngu/lazy-grid-template row-tokens) + row-spans (ngu/grid-spans row-tokens) + column-tokens (ngu/lazy-grid-tokens @column-traversal) + column-template (ngu/lazy-grid-template column-tokens) + column-spans (ngu/grid-spans column-tokens) + spacer-container [:div {:style {:border "thin solid lightblue"}}] + row-header-container [:div {:style {:display :grid + :grid-template-rows row-template + :grid-template-columns (ngu/grid-template row-header-widths)}}] + row-header-cells (for [path windowed-row-paths] + [:div {:style {:grid-row-start (ngu/path->grid-line-name path) + :grid-row-end (str "span " (get row-spans path)) + :grid-column-start (count path) + :grid-column-end (str "span " (+ 1 (- row-depth (count path)))) + :border-top "thin solid green" + :border-left "thin solid green" + :overflow :hidden + :font-size 8}} + (pr-str path)]) + column-header-container [:div {:style {:display :grid + :grid-template-rows (ngu/grid-template column-header-heights) + :grid-template-columns column-template}}] + column-header-cells (for [path windowed-column-paths] + [:div {:style {:grid-column-start (ngu/path->grid-line-name path) + :grid-column-end (str "span " (get column-spans path)) + :grid-row-start (count path) + :grid-row-end (str "span " (+ 1 (- column-depth (count path)))) + :border-top "thin solid green" + :border-left "thin solid green" + :overflow :hidden + :font-size 8}} + (pr-str path)]) + main-container [:div + {:style {:flex "0 0 auto" + :border "2px solid grey" + :display :grid + :grid-template-rows (ngu/grid-template [column-header-height-total row-height-total]) + :grid-template-columns (ngu/grid-template [row-header-width-total column-width-total])}}] + cell-grid-container [:div {:style {:display :grid + :grid-template-rows row-template + :grid-template-columns column-template}}] + cells (for [row-path windowed-row-leaf-paths + column-path windowed-column-leaf-paths] + (u/part cell {:row-path row-path :column-path column-path}))] + [rc/v-box + :style {:position :relative} + :children + [(conj main-container + spacer-container + (into column-header-container column-header-cells) + (into row-header-container row-header-cells) + (into cell-grid-container cells)) + [:div {:style {:position :absolute + :top (+ (* 2 @wy) column-header-height-total) + :left (+ @wx row-header-width-total) + :width @ww + :height @wh + :border "2px solid red"}}]]]))}))) (def row-tree (r/atom ngu/test-tree)) @@ -1141,18 +1171,24 @@ [rc/h-box :gap "50px" :children - [[new-nested-grid {:row-tree row-tree - :column-tree [:a :b :c :d :e :f :g :h :i :j :k]}] + [[rc/v-box + :children + [[new-nested-grid {:row-tree row-tree + :column-tree [:a [:b 30 :d 40] [:e 30 :g 35] [:h 10 :j] [:k 20]]}] + "Window width" + [rc/slider {:model ww :on-change (partial reset! ww) :min 50 :max 200}] + "Window height" + [rc/slider {:model wh :on-change (partial reset! wh) :min 50 :max 200}]]] [rc/box :style {:margin-top 50} :size "400px" :child [window-search-test {:tree ngu/test-tree}]] - [:<> [linear-search-infinite-scroll-test - {:row-height 25 - :column-width 100 - :max-height "80vh" - :max-width "80vw" - :row-seq row-seq - :column-seq column-seq - :cell test-cell}] - [:div "rows loaded:" @rows-loaded]]]]) + #_[:<> [linear-search-infinite-scroll-test + {:row-height 25 + :column-width 100 + :max-height "80vh" + :max-width "80vw" + :row-seq row-seq + :column-seq column-seq + :cell test-cell}] + [:div "rows loaded:" @rows-loaded]]]])