Skip to content

Commit 5dab060

Browse files
authored
Tool enhancements (#85)
* rename primary-tool to cached-tool * enhance circle tool * enhance ellipse tool * enhance line tool * enhance rect tool * enhance svg tool * enhance blob tool * reset history on tool activation * fix reset state * precision fixes * enhance pen tool * enhance measure tool * fix circle snap meta * enhance zoom tool * remove side effects from events * enhance transform tool * enhance brush tool * enhance polyshape tool * remove temp element leftovers * introduce cached state * remove unneeded deselect * fix reset state * fix offset on create * refactor * fix text create * enhance disabled state * path fixes * refactor * refactor * simplify tools * simplify svg tool
1 parent 5f5b8bd commit 5dab060

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+800
-601
lines changed

.clj-kondo/config.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
:unused-alias {:level :warning}
2020
:redundant-call {:level :warning}
2121
:redundant-str-call {:level :warning}
22-
:line-length {:max-line-length 100
22+
:line-length {:max-line-length 90
2323
:exclude-urls true}
2424
:clojure-lsp/unused-public-var {:exclude-regex #{"pages.*"}}
2525
:consistent-alias {:level :warning

src/electron/main.cljs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,9 @@
162162
:frame false}))
163163
(.once ^js @loading-window "show" init-main-window!)
164164
(.loadURL ^js @loading-window (resource-path "/public/loading.html"))
165-
(.once ^js (.-webContents @loading-window) "did-finish-load" #(.show ^js @loading-window)))
165+
(.once ^js (.-webContents @loading-window)
166+
"did-finish-load"
167+
#(.show ^js @loading-window)))
166168

167169
(defn ^:export init! []
168170
(.initialize log)

src/renderer/app/db.cljs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
(def App
3737
[:map {:closed true}
3838
[:tool {:default :transform} Tool]
39-
[:primary-tool {:optional true} Tool]
39+
[:cached-tool {:optional true} Tool]
4040
[:pointer-pos {:default [0 0]} Vec2]
4141
[:pointer-offset {:optional true} Vec2]
4242
[:adjusted-pointer-pos {:default [0 0]} Vec2]
@@ -49,6 +49,7 @@
4949
[:event-timestamp {:optional true} number?]
5050
[:double-click-delta {:default 250} [:and number? pos?]]
5151
[:state {:default :idle} State]
52+
[:cached-state {:optional true} State]
5253
[:grid {:default false :persist true} boolean?]
5354
[:ruler {:default {} :persist true} Ruler]
5455
[:snap {:default {} :persist true} Snap]

src/renderer/app/effects.cljs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@
4545
(fn [{:keys [on-success on-error formatter]}]
4646
(when-not (undefined? js/window.queryLocalFonts)
4747
(-> (.queryLocalFonts js/window)
48-
(.then #(when on-success (rf/dispatch (conj on-success (cond-> % formatter formatter)))))
48+
(.then #(when on-success (rf/dispatch (conj on-success
49+
(cond-> %
50+
formatter formatter)))))
4951
(.catch #(when on-error (rf/dispatch (conj on-error %))))))))
5052

5153
(rf/reg-fx

src/renderer/app/views.cljs

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,25 +44,39 @@
4444
(interpose ", " (map (fn [[k v]]
4545
^{:key k}
4646
[:span (str (name k) ": " (if (number? v)
47-
(.toFixed v 2)
47+
(.toFixed v 3)
4848
(coll->str v)))]) m)))
4949

5050
(defn debug-rows
5151
[]
52-
[["Dom rect" (map->str @(rf/subscribe [::app.subs/dom-rect]))]
53-
["Viewbox" (coll->str @(rf/subscribe [::frame.subs/viewbox]))]
54-
["Pointer position" (coll->str @(rf/subscribe [::app.subs/pointer-pos]))]
55-
["Adjusted pointer position" (coll->str @(rf/subscribe [::app.subs/adjusted-pointer-pos]))]
56-
["Pointer offset" (coll->str @(rf/subscribe [::app.subs/pointer-offset]))]
57-
["Adjusted pointer offset" (coll->str @(rf/subscribe [::app.subs/adjusted-pointer-offset]))]
58-
["Pointer drag?" (str @(rf/subscribe [::tool.subs/drag?]))]
59-
["Pan" (coll->str @(rf/subscribe [::document.subs/pan]))]
60-
["Active tool" @(rf/subscribe [::tool.subs/active])]
61-
["Primary tool" @(rf/subscribe [::tool.subs/primary])]
62-
["State" @(rf/subscribe [::tool.subs/state])]
63-
["Clicked element" (:id @(rf/subscribe [::app.subs/clicked-element]))]
64-
["Ignored elements" @(rf/subscribe [::document.subs/ignored-ids])]
65-
["Snap" (map->str @(rf/subscribe [::snap.subs/nearest-neighbor]))]])
52+
(let [dom-rect (rf/subscribe [::app.subs/dom-rect])
53+
viewbox (rf/subscribe [::frame.subs/viewbox])
54+
pointer-pos (rf/subscribe [::app.subs/pointer-pos])
55+
adjusted-pointer-pos (rf/subscribe [::app.subs/adjusted-pointer-pos])
56+
pointer-offset (rf/subscribe [::app.subs/pointer-offset])
57+
adjusted-pointer-offset (rf/subscribe [::app.subs/adjusted-pointer-offset])
58+
drag? (rf/subscribe [::tool.subs/drag?])
59+
pan (rf/subscribe [::document.subs/pan])
60+
active-tool (rf/subscribe [::tool.subs/active])
61+
cached-tool (rf/subscribe [::tool.subs/cached])
62+
tool-state (rf/subscribe [::tool.subs/state])
63+
clicked-element (rf/subscribe [::app.subs/clicked-element])
64+
ignored-ids (rf/subscribe [::document.subs/ignored-ids])
65+
nearest-neighbor (rf/subscribe [::snap.subs/nearest-neighbor])]
66+
[["Dom rect" (map->str @dom-rect)]
67+
["Viewbox" (coll->str @viewbox)]
68+
["Pointer position" (coll->str @pointer-pos)]
69+
["Adjusted pointer position" (coll->str @adjusted-pointer-pos)]
70+
["Pointer offset" (coll->str @pointer-offset)]
71+
["Adjusted pointer offset" (coll->str @adjusted-pointer-offset)]
72+
["Pointer drag?" (str @drag?)]
73+
["Pan" (coll->str @pan)]
74+
["Active tool" @active-tool]
75+
["Cached tool" @cached-tool]
76+
["State" @tool-state]
77+
["Clicked element" (:id @clicked-element)]
78+
["Ignored elements" @ignored-ids]
79+
["Snap" (map->str @nearest-neighbor)]]))
6680

6781
(defn debug-info
6882
[]
@@ -112,8 +126,9 @@
112126
(when (and help-bar (seq help-message))
113127
[:div.flex.absolute.justify-center.w-full.p-4.pointer-events-none
114128
[:div.bg-primary.rounded-full.overflow-hidden.shadow-lg
115-
[:div.overlay.text-color.text-xs.gap-1.flex.flex-wrap.truncate.py-2.px-4.justify-center
116-
{:aria-live "polite"}
129+
[:div.overlay.text-color.text-xs.gap-1.flex.flex-wrap.truncate.py-2
130+
{:class "px-4 justify-center"
131+
:aria-live "polite"}
117132
help-message]]])]]]))
118133

119134
(defn center-top-group

src/renderer/attribute/impl/core.cljs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@
194194

195195
(defmethod attribute.hierarchy/description [:default :values]
196196
[]
197-
"The values attribute has different meanings, depending upon the context where it's used,
198-
either it defines a sequence of values used over the course of an animation,
197+
"The values attribute has different meanings, depending upon the context where it's
198+
used, either it defines a sequence of values used over the course of an animation,
199199
or it's a list of numbers for a color matrix, which is interpreted differently
200200
depending on the type of color change to be performed.")
201201

src/renderer/attribute/impl/d.cljs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@
140140
[:> Popover/Root {:modal true}
141141
[:> Popover/Trigger
142142
{:title "Edit path"
143-
:class "form-control-button"}
143+
:class "form-control-button"
144+
:disabled disabled}
144145
[views/icon "pencil"]]
145146
[:> Popover/Portal
146147
[:> Popover/Content {:sideOffset 5

src/renderer/attribute/impl/font_weight.cljs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
"The font-weight attribute refers to the boldness or lightness of the glyphs
1313
used to render the text, relative to other fonts in the same font family.")
1414

15+
(defn label
16+
[weight]
17+
(let [weight-name (first (get utils.attribute/weight-name-mapping weight))]
18+
(str weight " - " weight-name)))
19+
1520
(defmethod attribute.hierarchy/form-element [:default :font-weight]
1621
[_ k v attrs]
1722
(let [available-weights @(rf/subscribe [::element.subs/font-weights])
@@ -22,7 +27,5 @@
2227
(merge attrs
2328
{:default-value "400"
2429
:items (mapv #(do {:key %
25-
:label (str % " - " (-> %
26-
utils.attribute/weight-name-mapping
27-
first))
30+
:label (label %)
2831
:value %}) weights)})]))

src/renderer/attribute/impl/href.cljs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
::success
4646
(fn [{:keys [db]} [_ file]]
4747
{:db (tool.handlers/activate db :transform)
48-
::effects/file-read-as [file
49-
:data-url
50-
{"load" {:on-fire [::element.events/set-attr :href]}
51-
"error" {:on-fire [::notification.events/show-exception]}}]}))
48+
::effects/file-read-as
49+
[file :data-url {"load" {:on-fire [::element.events/set-attr :href]}
50+
"error" {:on-fire [::notification.events/show-exception]}}]}))

src/renderer/attribute/impl/points.cljs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@
3838
[views/icon "times"]]])
3939

4040
(defn points-popover
41-
[points]
41+
[points disabled]
4242
[:> Popover/Root {:modal true}
4343
[:> Popover/Trigger
4444
{:title "Edit points"
45-
:class "form-control-button"}
45+
:class "form-control-button"
46+
:disabled disabled}
4647
[views/icon "pencil"]]
4748
[:> Popover/Portal
4849
[:> Popover/Content
@@ -64,4 +65,4 @@
6465
[:div.flex.gap-px.w-full
6566
[attribute.views/form-input k (if state-idle v "waiting")
6667
{:disabled (or disabled (not v) (not state-idle))}]
67-
(when v [points-popover (utils.utils.attribute/points->vec v)])]))
68+
(when v [points-popover (utils.utils.attribute/points->vec v) disabled])]))

src/renderer/attribute/views.cljs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
[renderer.event.impl.keyboard :as event.impl.keyboard]
1414
[renderer.events :as-alias events]
1515
[renderer.tool.hierarchy :as tool.hierarchy]
16+
[renderer.tool.subs :as-alias tool.subs]
1617
[renderer.utils.attribute :as utils.attribute]
1718
[renderer.views :as views]))
1819

@@ -95,8 +96,8 @@
9596
% v
9697
on-change-handler! k v)})]
9798
(when-not (or (empty? (str v)) disabled)
98-
[:button.button.bg-primary.text-muted.absolute.h-full.right-0.clear-input-button.invisible.p-1
99-
{:class "hover:bg-transparent"
99+
[:button.button.bg-primary.text-muted.absolute.h-full.right-0.p-1.invisible
100+
{:class "clear-input-button hover:bg-transparent"
100101
:on-pointer-down #(rf/dispatch [::element.events/remove-attr k])}
101102
[views/icon "times"]])])
102103

@@ -242,7 +243,12 @@
242243
(let [selected-elements @(rf/subscribe [::element.subs/selected])
243244
selected-tags @(rf/subscribe [::element.subs/selected-tags])
244245
selected-attrs @(rf/subscribe [::element.subs/selected-attrs])
245-
locked? @(rf/subscribe [::element.subs/selected-locked?])
246+
selected-locked? @(rf/subscribe [::element.subs/selected-locked?])
247+
tool-state @(rf/subscribe [::tool.subs/state])
248+
tool-cached-state @(rf/subscribe [::tool.subs/cached-state])
249+
locked? (or selected-locked?
250+
(not= tool-state :idle)
251+
(and tool-cached-state (not= tool-cached-state :idle)))
246252
tag (first selected-tags)
247253
multitag? (next selected-tags)]
248254
(when-first [el selected-elements]

src/renderer/dialog/views.cljs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,16 @@
4747
" will be lost if you close the document without saving."]
4848
[:div.flex.gap-2.flex-wrap
4949
[:button.button.px-2.bg-primary.rounded.flex-1
50-
{:on-click #(rf/dispatch [::dialog.events/close [::document.events/close id false]])}
50+
{:on-click #(rf/dispatch [::dialog.events/close
51+
[::document.events/close id false]])}
5152
"Don't save"]
5253
[:button.button.px-2.bg-primary.rounded.flex-1
5354
{:on-click #(rf/dispatch [::dialog.events/close])}
5455
"Cancel"]
5556
[:button.button.px-2.rounded.flex-1.accent
5657
{:auto-focus true
57-
:on-click #(rf/dispatch [::dialog.events/close [::document.events/save-and-close id]])}
58+
:on-click #(rf/dispatch [::dialog.events/close
59+
[::document.events/save-and-close id]])}
5860
"Save"]]])
5961

6062
(defn cmdk-item

src/renderer/document/db.cljs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
[:zoom {:default 1} ZoomFactor]
2424
[:rotate {:default 0} number?]
2525
[:history {:optional true} History]
26-
[:temp-element {:optional true} Element]
2726
[:pan {:default [0 0]} Vec2]
2827
[:elements {:default {} :persist true} [:map-of uuid? Element]]
2928
[:focused {:optional true} boolean?]

src/renderer/document/subs.cljs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,6 @@
103103
:<- [::active]
104104
:-> :elements)
105105

106-
(rf/reg-sub
107-
::temp-element
108-
:<- [::active]
109-
:-> :temp-element)
110-
111106
(rf/reg-sub
112107
::filter
113108
:<- [::active]

src/renderer/effects.cljs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@
150150
(.addEventListener target
151151
channel
152152
#(rf/dispatch (conj listener
153-
(cond-> % formatter formatter))))))
153+
(cond-> %
154+
formatter formatter))))))
154155

155156
(rf/reg-fx
156157
::ipc-send
@@ -163,7 +164,8 @@
163164
(fn [{:keys [channel data formatter on-success on-error]}]
164165
(when js/window.api
165166
(-> (js/window.api.invoke channel (clj->js data))
166-
(.then #(when on-success (rf/dispatch (conj on-success (cond-> % formatter formatter)))))
167+
(.then #(when on-success (rf/dispatch (conj on-success (cond-> %
168+
formatter formatter)))))
167169
(.catch #(when on-error (rf/dispatch (conj on-error %))))))))
168170

169171
(rf/reg-fx

src/renderer/element/impl/box.cljs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,17 @@
2323

2424
(defmethod element.hierarchy/edit ::element.hierarchy/box
2525
[el [x y] handle]
26-
(case handle
27-
:position
28-
(-> (utils.element/update-attrs-with el (comp (partial max 0) -) [[:width x] [:height y]])
29-
(element.hierarchy/translate [x y]))
26+
(let [clamp (partial max 0)]
27+
(case handle
28+
:position
29+
(-> el
30+
(utils.element/update-attrs-with (comp clamp -) [[:width x] [:height y]])
31+
(element.hierarchy/translate [x y]))
3032

31-
:size
32-
(utils.element/update-attrs-with el (comp (partial max 0) +) [[:width x] [:height y]])
33+
:size
34+
(utils.element/update-attrs-with el (comp clamp +) [[:width x] [:height y]])
3335

34-
el))
36+
el)))
3537

3638
(defmethod element.hierarchy/render-edit ::element.hierarchy/box
3739
[el]

src/renderer/element/impl/container/canvas.cljs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,18 @@
3030
(let [child-elements @(rf/subscribe [::element.subs/filter-visible (:children el)])
3131
viewbox-attr @(rf/subscribe [::frame.subs/viewbox-attr])
3232
{:keys [width height]} @(rf/subscribe [::app.subs/dom-rect])
33-
temp-element @(rf/subscribe [::document.subs/temp-element])
3433
read-only? @(rf/subscribe [::document.subs/read-only?])
3534
cursor @(rf/subscribe [::tool.subs/cursor])
3635
active-tool @(rf/subscribe [::tool.subs/active])
37-
primary-tool @(rf/subscribe [::tool.subs/primary])
36+
cached-tool @(rf/subscribe [::tool.subs/cached])
3837
rotate @(rf/subscribe [::document.subs/rotate])
3938
grid @(rf/subscribe [::app.subs/grid])
4039
pointer-handler #(event.pointer/handler! % el)
4140
snap? @(rf/subscribe [::snap.subs/active?])
4241
nearest-neighbor @(rf/subscribe [::snap.subs/nearest-neighbor])
4342
snapped-el-id (-> nearest-neighbor meta :id)
44-
snapped-el (when snapped-el-id @(rf/subscribe [::element.subs/entity snapped-el-id]))]
43+
snapped-el (when snapped-el-id
44+
@(rf/subscribe [::element.subs/entity snapped-el-id]))]
4545
[:svg#canvas {:on-pointer-up pointer-handler
4646
:on-pointer-down pointer-handler
4747
:on-pointer-move pointer-handler
@@ -66,16 +66,14 @@
6666

6767
(when grid [ruler.views/grid])
6868

69-
(when-not read-only? [element.hierarchy/render temp-element])
70-
7169
(when snap?
7270
[:<>
7371
(when snapped-el
7472
[utils.svg/bounding-box (:bbox snapped-el) true])
7573
(when nearest-neighbor
7674
[snap.views/canvas-label nearest-neighbor])])
7775

78-
(when-not read-only? [tool.hierarchy/render (or primary-tool active-tool)])]))
76+
(when-not read-only? [tool.hierarchy/render (or cached-tool active-tool)])]))
7977

8078
(defmethod element.hierarchy/render-to-string :canvas
8179
[el]

src/renderer/element/impl/custom/brush.cljs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@
165165
#(->> (into [] partition-to-px (utils.attribute/str->seq %))
166166
(reduce (fn [points point]
167167
(let [rel-point (matrix/sub bbox-min (take 2 point))
168-
rel-offset (utils.element/scale-offset ratio rel-point)
168+
rel-offset (utils.element/scale-offset ratio
169+
rel-point)
169170
offset (matrix/add offset rel-offset)]
170171
(translate offset points point))) [])
171172
(string/join " ")))))
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
(ns renderer.element.impl.custom.core
22
(:require
33
[renderer.element.impl.custom.blob]
4-
[renderer.element.impl.custom.brush]
5-
[renderer.element.impl.custom.measure]))
4+
[renderer.element.impl.custom.brush]))

0 commit comments

Comments
 (0)