mirror of
https://github.com/penpot/penpot.git
synced 2025-03-12 07:41:43 -05:00
✨ Created bool shapes
This commit is contained in:
parent
5031700af6
commit
9f08153a85
8 changed files with 276 additions and 8 deletions
59
common/src/app/common/pages/changes_builder.cljc
Normal file
59
common/src/app/common/pages/changes_builder.cljc
Normal file
|
@ -0,0 +1,59 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.common.pages.changes-builder)
|
||||
|
||||
;; Auxiliary functions to help create a set of changes (undo + redo)
|
||||
|
||||
(defn empty-changes [origin page-id]
|
||||
(with-meta
|
||||
{:redo-changes []
|
||||
:undo-changes []
|
||||
:origin origin}
|
||||
{::page-id page-id}))
|
||||
|
||||
(defn add-obj
|
||||
[changes obj]
|
||||
(let [add-change
|
||||
{:type :add-obj
|
||||
:id (:id obj)
|
||||
:page-id (::page-id (meta changes))
|
||||
:parent-id (:parent-id obj)
|
||||
:frame-id (:frame-id obj)
|
||||
:index (::index obj)
|
||||
:obj (dissoc obj ::index :parent-id)}
|
||||
|
||||
del-change
|
||||
{:type :del-obj
|
||||
:id (:id obj)
|
||||
:page-id (::page-id (meta changes))}]
|
||||
|
||||
(-> changes
|
||||
(update :redo-changes conj add-change)
|
||||
(update :undo-changes #(into [del-change] %)))))
|
||||
|
||||
(defn change-parent
|
||||
[changes parent-id shapes]
|
||||
(let [set-parent-change
|
||||
{:type :mov-objects
|
||||
:parent-id parent-id
|
||||
:page-id (::page-id (meta changes))
|
||||
:shapes (->> shapes (mapv :id))}
|
||||
|
||||
mk-undo-change
|
||||
(fn [shape]
|
||||
{:type :mov-objects
|
||||
:page-id (::page-id (meta changes))
|
||||
:parent-id (:parent-id shape)
|
||||
:shapes [(:id shape)]
|
||||
:index (::index shape)})
|
||||
|
||||
undo-moves
|
||||
(->> shapes (mapv mk-undo-change))]
|
||||
|
||||
(-> changes
|
||||
(update :redo-changes conj set-parent-change)
|
||||
(update :undo-changes #(into undo-moves %)))))
|
|
@ -23,6 +23,7 @@
|
|||
[app.config :as cfg]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.data.workspace.booleans :as dwb]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.drawing :as dwd]
|
||||
|
@ -48,7 +49,8 @@
|
|||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]))
|
||||
[potok.core :as ptk]
|
||||
))
|
||||
|
||||
;; (log/set-level! :trace)
|
||||
|
||||
|
@ -1100,6 +1102,10 @@
|
|||
:group
|
||||
(rx/of (dwc/select-shapes (into (d/ordered-set) [(last shapes)])))
|
||||
|
||||
:bool
|
||||
;; TODO
|
||||
(js/alert "TODO")
|
||||
|
||||
:svg-raw
|
||||
nil
|
||||
|
||||
|
@ -1987,3 +1993,6 @@
|
|||
(d/export dwg/unmask-group)
|
||||
(d/export dwg/group-selected)
|
||||
(d/export dwg/ungroup-selected)
|
||||
|
||||
;; Boolean
|
||||
(d/export dwb/create-bool)
|
||||
|
|
66
frontend/src/app/main/data/workspace/booleans.cljs
Normal file
66
frontend/src/app/main/data/workspace/booleans.cljs
Normal file
|
@ -0,0 +1,66 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.main.data.workspace.booleans
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.changes-builder :as cb]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[beicon.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
(defn selected-shapes
|
||||
[state]
|
||||
(let [objects (wsh/lookup-page-objects state)]
|
||||
(->> (wsh/lookup-selected state)
|
||||
(cp/clean-loops objects)
|
||||
(map #(get objects %))
|
||||
(filter #(not= :frame (:type %)))
|
||||
(map #(assoc % ::index (cp/position-on-parent (:id %) objects)))
|
||||
(sort-by ::index))))
|
||||
|
||||
(defn create-bool-data
|
||||
[type name shapes]
|
||||
(let [head (first shapes)
|
||||
selrect (gsh/selection-rect shapes)]
|
||||
(-> {:id (uuid/next)
|
||||
:type :bool
|
||||
:bool-type type
|
||||
:frame-id (:frame-id head)
|
||||
:parent-id (:parent-id head)
|
||||
:name name
|
||||
::index (::index head)
|
||||
:shapes []}
|
||||
(gsh/setup selrect))))
|
||||
|
||||
|
||||
(defn create-bool
|
||||
[bool-type]
|
||||
(ptk/reify ::create-bool-union
|
||||
ptk/WatchEvent
|
||||
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
base-name (-> bool-type d/name str/capital (str "-1"))
|
||||
name (-> (dwc/retrieve-used-names objects)
|
||||
(dwc/generate-unique-name base-name))
|
||||
shapes (selected-shapes state)]
|
||||
|
||||
(when-not (empty? shapes)
|
||||
(let [boolean-data (create-bool-data bool-type name shapes)
|
||||
shape-id (:id boolean-data)
|
||||
changes (-> (cb/empty-changes it page-id)
|
||||
(cb/add-obj boolean-data)
|
||||
(cb/change-parent shape-id shapes))]
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwc/select-shapes (d/ordered-set shape-id)))))))))
|
|
@ -260,6 +260,11 @@
|
|||
:command ["alt" "."]
|
||||
:type "keyup"
|
||||
:fn #(st/emit! (dw/toggle-distances-display false))}
|
||||
|
||||
:create-union {:tooltip (ds/alt "U")
|
||||
:command ["alt" "u"]
|
||||
:fn #(st/emit! (dw/create-bool :union))}
|
||||
|
||||
})
|
||||
|
||||
(defn get-tooltip [shortcut]
|
||||
|
|
75
frontend/src/app/main/ui/shapes/bool.cljs
Normal file
75
frontend/src/app/main/ui/shapes/bool.cljs
Normal file
|
@ -0,0 +1,75 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.shapes.bool
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.util.object :as obj]
|
||||
[app.util.path.bool :as pb]
|
||||
[app.util.path.geom :as upg]
|
||||
[app.util.path.shapes-to-path :as stp]
|
||||
[clojure.set :as set]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(mf/defc path-points
|
||||
[{:keys [points color]}]
|
||||
|
||||
[:*
|
||||
(for [[idx {:keys [x y]}] (d/enumerate points)]
|
||||
[:circle {:key (str "circle-" idx)
|
||||
:cx x
|
||||
:cy y
|
||||
:r 5
|
||||
:style {:fill color
|
||||
;;:fillOpacity 0.5
|
||||
}}])])
|
||||
|
||||
(defn bool-shape
|
||||
[shape-wrapper]
|
||||
(mf/fnc bool-shape
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [frame (obj/get props "frame")
|
||||
childs (obj/get props "childs")
|
||||
shape-1 (stp/convert-to-path (nth childs 0))
|
||||
shape-2 (stp/convert-to-path (nth childs 1))
|
||||
|
||||
content-1 (-> shape-1 gsh/transform-shape (gsh/translate-to-frame frame) :content)
|
||||
content-2 (-> shape-2 gsh/transform-shape (gsh/translate-to-frame frame) :content)
|
||||
|
||||
|
||||
[content-1' content-2'] (pb/content-intersect-split content-1 content-2)
|
||||
|
||||
points-1 (->> (upg/content->points content-1')
|
||||
(map #(hash-map :x (mth/round (:x %))
|
||||
:y (mth/round (:y %))))
|
||||
(into #{}))
|
||||
|
||||
points-2 (->> (upg/content->points content-2')
|
||||
(map #(hash-map :x (mth/round (:x %))
|
||||
:y (mth/round (:y %))))
|
||||
(into #{}))
|
||||
|
||||
points-3 (set/intersection points-1 points-2)]
|
||||
|
||||
[:*
|
||||
[:& shape-wrapper {:shape (-> shape-1 #_(assoc :content content-1'))
|
||||
:frame frame}]
|
||||
|
||||
[:& shape-wrapper {:shape (-> shape-2 #_(assoc :content content-2'))
|
||||
:frame frame}]
|
||||
|
||||
[:& path-points {:points points-1 :color "#FF0000"}]
|
||||
[:& path-points {:points points-2 :color "#0000FF"}]
|
||||
[:& path-points {:points points-3 :color "#FF00FF"}]
|
||||
|
||||
|
||||
])))
|
||||
|
||||
|
||||
|
|
@ -98,8 +98,14 @@
|
|||
:on-accept confirm-update-remote-component}))
|
||||
do-show-component (st/emitf (dw/go-to-layout :assets))
|
||||
do-navigate-component-file (st/emitf (dwl/nav-to-component-file
|
||||
(:component-file shape)))]
|
||||
(:component-file shape)))
|
||||
|
||||
do-create-bool-shape (st/emitf (dw/create-bool :union))]
|
||||
[:*
|
||||
;;
|
||||
[:& menu-entry {:title ">BOOL"
|
||||
:on-click do-create-bool-shape}]
|
||||
;;
|
||||
[:& menu-entry {:title (tr "workspace.shape.menu.copy")
|
||||
:shortcut (sc/get-tooltip :copy)
|
||||
:on-click do-copy}]
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
[app.main.ui.shapes.image :as image]
|
||||
[app.main.ui.shapes.rect :as rect]
|
||||
[app.main.ui.shapes.text.fontfaces :as ff]
|
||||
[app.main.ui.workspace.shapes.bool :as bool]
|
||||
[app.main.ui.workspace.shapes.bounding-box :refer [bounding-box]]
|
||||
[app.main.ui.workspace.shapes.common :as common]
|
||||
[app.main.ui.workspace.shapes.frame :as frame]
|
||||
|
@ -35,6 +36,7 @@
|
|||
(declare shape-wrapper)
|
||||
(declare group-wrapper)
|
||||
(declare svg-raw-wrapper)
|
||||
(declare bool-wrapper)
|
||||
(declare frame-wrapper)
|
||||
|
||||
(def circle-wrapper (common/generic-wrapper-factory circle/circle-shape))
|
||||
|
@ -92,13 +94,14 @@
|
|||
[:*
|
||||
(if-not svg-element?
|
||||
(case (:type shape)
|
||||
:path [:> path/path-wrapper opts]
|
||||
:text [:> text/text-wrapper opts]
|
||||
:group [:> group-wrapper opts]
|
||||
:rect [:> rect-wrapper opts]
|
||||
:image [:> image-wrapper opts]
|
||||
:circle [:> circle-wrapper opts]
|
||||
:path [:> path/path-wrapper opts]
|
||||
:text [:> text/text-wrapper opts]
|
||||
:group [:> group-wrapper opts]
|
||||
:rect [:> rect-wrapper opts]
|
||||
:image [:> image-wrapper opts]
|
||||
:circle [:> circle-wrapper opts]
|
||||
:svg-raw [:> svg-raw-wrapper opts]
|
||||
:bool [:> bool-wrapper opts]
|
||||
|
||||
;; Only used when drawing a new frame.
|
||||
:frame [:> frame-wrapper {:shape shape}]
|
||||
|
@ -113,5 +116,6 @@
|
|||
|
||||
(def group-wrapper (group/group-wrapper-factory shape-wrapper))
|
||||
(def svg-raw-wrapper (svg-raw/svg-raw-wrapper-factory shape-wrapper))
|
||||
(def bool-wrapper (bool/bool-wrapper-factory shape-wrapper))
|
||||
(def frame-wrapper (frame/frame-wrapper-factory shape-wrapper))
|
||||
|
||||
|
|
44
frontend/src/app/main/ui/workspace/shapes/bool.cljs
Normal file
44
frontend/src/app/main/ui/workspace/shapes/bool.cljs
Normal file
|
@ -0,0 +1,44 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.workspace.shapes.bool
|
||||
(:require
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.ui.shapes.bool :as bool]
|
||||
[app.main.ui.shapes.shape :refer [shape-container]]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(defn use-double-click [{:keys [id]}]
|
||||
(mf/use-callback
|
||||
(mf/deps id)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (dw/select-inside-group id @ms/mouse-position)))))
|
||||
|
||||
(defn bool-wrapper-factory
|
||||
[shape-wrapper]
|
||||
(let [shape-component (bool/bool-shape shape-wrapper)]
|
||||
(mf/fnc bool-wrapper
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["shape" "frame"]))]
|
||||
::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
frame (unchecked-get props "frame")
|
||||
|
||||
childs-ref (mf/use-memo (mf/deps shape) #(refs/objects-by-id (:shapes shape) {:with-modifiers? true}))
|
||||
childs (mf/deref childs-ref)]
|
||||
|
||||
[:> shape-container {:shape shape}
|
||||
[:& shape-component
|
||||
{:frame frame
|
||||
:shape shape
|
||||
:childs childs}]]))))
|
||||
|
Loading…
Add table
Reference in a new issue