Handling groups inside bool shapes

This commit is contained in:
alonso.torres 2021-09-17 14:38:44 +02:00
parent 6fd35ae5d9
commit c56f024a86
7 changed files with 155 additions and 51 deletions

View file

@ -11,6 +11,7 @@
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes.common :as gsc] [app.common.geom.shapes.common :as gsc]
[app.common.geom.shapes.path :as gsp] [app.common.geom.shapes.path :as gsp]
[app.common.path.bool :as pb]
[app.common.path.commands :as pc])) [app.common.path.commands :as pc]))
(def ^:const bezier-circle-c 0.551915024494) (def ^:const bezier-circle-c 0.551915024494)
@ -24,26 +25,31 @@
#{:rect #{:rect
:circle :circle
:image :image
:group}) :group
:bool})
(def ^:const style-group-properties
[:shadow
:blur])
(def ^:const style-properties (def ^:const style-properties
[:fill-color (d/concat
:fill-opacity style-group-properties
:fill-color-gradient [:fill-color
:fill-color-ref-file :fill-opacity
:fill-color-ref-id :fill-color-gradient
:fill-image :fill-color-ref-file
:stroke-color :fill-color-ref-id
:stroke-color-ref-file :fill-image
:stroke-color-ref-id :stroke-color
:stroke-opacity :stroke-color-ref-file
:stroke-style :stroke-color-ref-id
:stroke-width :stroke-opacity
:stroke-alignment :stroke-style
:stroke-cap-start :stroke-width
:stroke-cap-end :stroke-alignment
:shadow :stroke-cap-start
:blur]) :stroke-cap-end]))
(defn make-corner-arc (defn make-corner-arc
"Creates a curvle corner for border radius" "Creates a curvle corner for border radius"
@ -142,7 +148,6 @@
(defn group-to-path (defn group-to-path
[group objects] [group objects]
(let [xform (comp (map #(get objects %)) (let [xform (comp (map #(get objects %))
(map #(-> (convert-to-path % objects)))) (map #(-> (convert-to-path % objects))))
@ -157,6 +162,22 @@
(merge head-data) (merge head-data)
(d/without-keys dissoc-attrs)))) (d/without-keys dissoc-attrs))))
(defn bool-to-path
[shape objects]
(let [children (->> (:shapes shape)
(map #(get objects %))
(map #(convert-to-path % objects)))
head (first children)
head-data (select-keys head style-properties)
content (pb/content-bool (:bool-type shape) (mapv :content children))]
(-> shape
(assoc :type :path)
(assoc :content content)
(merge head-data)
(d/without-keys dissoc-attrs))))
(defn convert-to-path (defn convert-to-path
"Transforms the given shape to a path" "Transforms the given shape to a path"
[{:keys [type x y width height r1 r2 r3 r4 rx metadata] :as shape} objects] [{:keys [type x y width height r1 r2 r3 r4 rx metadata] :as shape} objects]
@ -165,6 +186,9 @@
(= (:type shape) :group) (= (:type shape) :group)
(group-to-path shape objects) (group-to-path shape objects)
(= (:type shape) :bool)
(bool-to-path shape objects)
(contains? allowed-transform-types type) (contains? allowed-transform-types type)
(let [new-content (let [new-content
(case type (case type

View file

@ -46,5 +46,13 @@
fill: $color-gray-40; fill: $color-gray-40;
} }
} }
&.selected svg {
fill: $color-primary;
}
&.selected:hover svg {
fill: $color-white;
}
} }
} }

View file

@ -1098,13 +1098,9 @@
:text :text
(rx/of (dwc/start-edition-mode id)) (rx/of (dwc/start-edition-mode id))
:group (:group :bool)
(rx/of (dwc/select-shapes (into (d/ordered-set) [(last shapes)]))) (rx/of (dwc/select-shapes (into (d/ordered-set) [(last shapes)])))
:bool
;; TODO
(js/alert "TODO")
:svg-raw :svg-raw
nil nil
@ -1995,3 +1991,6 @@
;; Boolean ;; Boolean
(d/export dwb/create-bool) (d/export dwb/create-bool)
(d/export dwb/group-to-bool)
(d/export dwb/bool-to-group)
(d/export dwb/change-bool-type)

View file

@ -45,11 +45,36 @@
(merge head-data) (merge head-data)
(gsh/update-bool-selrect shapes objects)))) (gsh/update-bool-selrect shapes objects))))
(defn group->bool
[group bool-type objects]
(let [shapes (->> (:shapes group)
(map #(get objects %))
(mapv #(stp/convert-to-path % objects)))
head (first shapes)
head-data (select-keys head stp/style-properties)]
(-> group
(assoc :type :bool)
(assoc :bool-type bool-type)
(merge head-data)
(gsh/update-bool-selrect shapes objects))))
(defn bool->group
[shape objects]
(let [children (->> (:shapes shape)
(mapv #(get objects %)))]
(-> shape
(assoc :type :group)
(dissoc :bool-type)
(d/without-keys stp/style-group-properties)
(gsh/update-group-selrect children))))
(defn create-bool (defn create-bool
[bool-type] [bool-type]
(ptk/reify ::create-bool-union (ptk/reify ::create-bool-union
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(let [page-id (:current-page-id state) (let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state) objects (wsh/lookup-page-objects state)
@ -66,3 +91,29 @@
(cb/change-parent shape-id shapes))] (cb/change-parent shape-id shapes))]
(rx/of (dch/commit-changes changes) (rx/of (dch/commit-changes changes)
(dwc/select-shapes (d/ordered-set shape-id))))))))) (dwc/select-shapes (d/ordered-set shape-id)))))))))
(defn group-to-bool
[shape-id bool-type]
(ptk/reify ::group-to-bool
ptk/WatchEvent
(watch [_ state _]
(let [objects (wsh/lookup-page-objects state)]
(rx/of (dch/update-shapes [shape-id] #(group->bool % bool-type objects)))))))
(defn bool-to-group
[shape-id]
(ptk/reify ::bool-to-group
ptk/WatchEvent
(watch [_ state _]
(let [objects (wsh/lookup-page-objects state)]
(rx/of (dch/update-shapes [shape-id] #(bool->group % objects)))))))
(defn change-bool-type
[shape-id bool-type]
(ptk/reify ::change-bool-type
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dch/update-shapes
[shape-id]
#(assoc % :bool-type bool-type))))))

View file

@ -266,8 +266,10 @@
(-> (:workspace-local state) (-> (:workspace-local state)
(select-keys [:modifiers :selected])) (select-keys [:modifiers :selected]))
modifiers (merge modifiers modifiers
(into #{} (map #(vector % disp-modifiers)) selected))] (d/deep-merge
modifiers
(into {} (map #(vector % {:modifiers disp-modifiers})) selected))]
(gsh/merge-modifiers children modifiers)))] (gsh/merge-modifiers children modifiers)))]
(l/derived selector st/state =))) (l/derived selector st/state =)))

View file

@ -6,6 +6,8 @@
(ns app.main.ui.shapes.bool (ns app.main.ui.shapes.bool
(:require (:require
[app.common.data :as d]
[app.common.geom.shapes :as gsh]
[app.common.path.bool :as pb] [app.common.path.bool :as pb]
[app.common.path.shapes-to-path :as stp] [app.common.path.shapes-to-path :as stp]
[app.main.ui.hooks :refer [use-equal-memo]] [app.main.ui.hooks :refer [use-equal-memo]]
@ -27,12 +29,12 @@
(mf/use-memo (mf/use-memo
(mf/deps childs) (mf/deps childs)
(fn [] (fn []
(->> shape (let [childs (d/mapm #(gsh/transform-shape %2) childs)]
:shapes (->> (:shapes shape)
(map #(get childs %)) (map #(get childs %))
(map #(stp/convert-to-path % childs)) (map #(stp/convert-to-path % childs))
(mapv :content) (mapv :content)
(pb/content-bool (:bool-type shape)))))] (pb/content-bool (:bool-type shape))))))]
[:& shape-wrapper {:shape (-> shape [:& shape-wrapper {:shape (-> shape
(assoc :type :path) (assoc :type :path)

View file

@ -6,49 +6,67 @@
(ns app.main.ui.workspace.sidebar.options.menus.booleans (ns app.main.ui.workspace.sidebar.options.menus.booleans
(:require (:require
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[rumext.alpha :as mf] [rumext.alpha :as mf]))
))
(mf/defc booleans-options (mf/defc booleans-options
[] []
(let [selected (mf/deref refs/selected-shapes) (let [selected (mf/deref refs/selected-objects)
disabled (and (some? selected) disabled (or (empty? selected)
(<= (count selected) 1)) (and (<= (count selected) 1)
(not (contains? #{:group :bool} (:type (first selected))))))
do-boolean-union (st/emitf (dw/create-bool :union)) head (first selected)
do-boolean-difference (st/emitf (dw/create-bool :difference)) is-group? (and (some? head) (= :group (:type head)))
do-boolean-intersection (st/emitf (dw/create-bool :intersection)) is-bool? (and (some? head) (= :bool (:type head)))
do-boolean-exclude (st/emitf (dw/create-bool :exclude))] head-bool-type (and (some? head) (:bool-type head))
set-bool
(fn [bool-type]
#(cond
(> (count selected) 1)
(st/emit! (dw/create-bool bool-type))
(and (= (count selected) 1) is-group?)
(st/emit! (dw/group-to-bool (:id head) bool-type))
(and (= (count selected) 1) is-bool?)
(if (= head-bool-type bool-type)
(st/emit! (dw/bool-to-group (:id head)))
(st/emit! (dw/change-bool-type (:id head) bool-type)))))]
[:div.align-options [:div.align-options
[:div.align-group [:div.align-group
[:div.align-button.tooltip.tooltip-bottom [:div.align-button.tooltip.tooltip-bottom
{:alt (tr "workspace.shape.menu.union") {:alt (tr "workspace.shape.menu.union")
:class (when disabled "disabled") :class (dom/classnames :disabled disabled
:on-click do-boolean-union} :selected (= head-bool-type :union))
:on-click (set-bool :union)}
i/boolean-union] i/boolean-union]
[:div.align-button.tooltip.tooltip-bottom [:div.align-button.tooltip.tooltip-bottom
{:alt (tr "workspace.shape.menu.difference") {:alt (tr "workspace.shape.menu.difference")
:class (when disabled "disabled") :class (dom/classnames :disabled disabled
:on-click do-boolean-difference} :selected (= head-bool-type :difference))
:on-click (set-bool :difference)}
i/boolean-difference] i/boolean-difference]
[:div.align-button.tooltip.tooltip-bottom [:div.align-button.tooltip.tooltip-bottom
{:alt (tr "workspace.shape.menu.intersection") {:alt (tr "workspace.shape.menu.intersection")
:class (when disabled "disabled") :class (dom/classnames :disabled disabled
:on-click do-boolean-intersection} :selected (= head-bool-type :intersection))
:on-click (set-bool :intersection)}
i/boolean-intersection] i/boolean-intersection]
[:div.align-button.tooltip.tooltip-bottom [:div.align-button.tooltip.tooltip-bottom
{:alt (tr "workspace.shape.menu.exclude") {:alt (tr "workspace.shape.menu.exclude")
:class (when disabled "disabled") :class (dom/classnames :disabled disabled
:on-click do-boolean-exclude} :selected (= head-bool-type :exclude))
:on-click (set-bool :exclude)}
i/boolean-exclude]]])) i/boolean-exclude]]]))