mirror of
https://github.com/penpot/penpot.git
synced 2025-04-16 00:41:25 -05:00
Add support for line rendering.
This commit is contained in:
parent
32b7bfe383
commit
e96eb76d84
5 changed files with 108 additions and 65 deletions
|
@ -191,21 +191,22 @@
|
|||
sh/-rotate rotation))))
|
||||
|
||||
(defn update-shape-size
|
||||
[sid {:keys [width height lock] :as opts}]
|
||||
"A helper event just for update the position
|
||||
of the shape using the width and heigt attrs
|
||||
instread final point of coordinates.
|
||||
|
||||
WARN: only works with shapes that works
|
||||
with height and width such are"
|
||||
[sid {:keys [width height] :as opts}]
|
||||
(sc/validate! +shape-update-size-schema+ opts)
|
||||
(reify
|
||||
rs/UpdateEvent
|
||||
(-apply-update [_ state]
|
||||
(let [shape (get-in state [:shapes-by-id sid])
|
||||
size (select-keys shape [:width :height])
|
||||
size (merge size
|
||||
(when width {:width width})
|
||||
(when height {:height height}))]
|
||||
(update-in state [:shapes-by-id sid]
|
||||
shapes/-resize size)))))
|
||||
(let [size [width height]]
|
||||
(update-in state [:shapes-by-id sid] sh/-resize' size)))))
|
||||
|
||||
(defn update-shape-position
|
||||
[sid {:keys [x y] :as opts}]
|
||||
[sid {:keys [x1 y1 x2 y2] :as opts}]
|
||||
(sc/validate! +shape-update-position-schema+ opts)
|
||||
(reify
|
||||
rs/UpdateEvent
|
||||
|
|
|
@ -45,6 +45,10 @@
|
|||
dispatch-by-type
|
||||
:hierarchy #'+hierarchy+)
|
||||
|
||||
(defmulti -resize'
|
||||
dispatch-by-type
|
||||
:hierarchy #'+hierarchy+)
|
||||
|
||||
(defmulti -rotate
|
||||
dispatch-by-type
|
||||
:hierarchy #'+hierarchy+)
|
||||
|
@ -70,20 +74,56 @@
|
|||
;; Implementation
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Initialize
|
||||
|
||||
(defmethod -initialize ::shape
|
||||
[shape props]
|
||||
(merge shape props))
|
||||
[shape {:keys [x1 y1 x2 y2]}]
|
||||
(merge shape
|
||||
(when x1 {:x x1})
|
||||
(when y1 {:y y1})
|
||||
(when (and x2 x1) {:width (- x2 x1)})
|
||||
(when (and y2 y1) {:height (- y2 y1)})))
|
||||
|
||||
(defmethod -initialize :builtin/group
|
||||
[shape {:keys [x y width height]}]
|
||||
[shape {:keys [x1 y1 x2 y2]}]
|
||||
shape)
|
||||
|
||||
;; (defmethod -initialize :builtin/line
|
||||
;; [shape {:keys [x y width height]}]
|
||||
;; (merge shape
|
||||
;; {:x1 x :y1 y
|
||||
;; :x2 (+ x width)
|
||||
;; :y2 (+ y height)}))
|
||||
(defmethod -initialize :builtin/line
|
||||
[shape {:keys [x1 y1 x2 y2]}]
|
||||
(merge shape
|
||||
(when x1 {:x1 x1})
|
||||
(when y1 {:y1 y1})
|
||||
(when x2 {:x2 x2})
|
||||
(when y2 {:y2 y2})))
|
||||
|
||||
;; Resize
|
||||
|
||||
(defmethod -resize :builtin/line
|
||||
[shape [x2 y2]]
|
||||
(assoc shape
|
||||
:x2 x2 :y2 y2))
|
||||
|
||||
(defmethod -resize :default
|
||||
[shape _]
|
||||
(throw (ex-info "Not implemented" (select-keys shape [:type]))))
|
||||
|
||||
(defmethod -resize' :builtin/icon
|
||||
[shape [width height]]
|
||||
(merge shape
|
||||
(when width {:width width})
|
||||
(when height {:height height})))
|
||||
|
||||
(defmethod -resize' :builtin/group
|
||||
[shape [width height]]
|
||||
(merge shape
|
||||
(when width {:width width})
|
||||
(when height {:height height})))
|
||||
|
||||
(defmethod -resize' :default
|
||||
[shape _]
|
||||
(throw (ex-info "Not implemented" (select-keys shape [:type]))))
|
||||
|
||||
;; Move
|
||||
|
||||
(defmethod -move ::shape
|
||||
[shape {:keys [dx dy] :as opts}]
|
||||
|
@ -97,23 +137,13 @@
|
|||
:dx (+ (:dx shape 0) dx)
|
||||
:dy (+ (:dy shape 0) dy)))
|
||||
|
||||
;; (defmethod -move :builtin/line
|
||||
;; [shape {:keys [dx dy] :as opts}]
|
||||
;; (assoc shape
|
||||
;; :x1 (+ (:x1 shape) dx)
|
||||
;; :y1 (+ (:y1 shape) dy)
|
||||
;; :x2 (+ (:x2 shape) dx)
|
||||
;; :y2 (+ (:y2 shape) dy)))
|
||||
|
||||
(defmethod -resize ::shape
|
||||
[shape {:keys [width height] :as opts}]
|
||||
(defmethod -move :builtin/line
|
||||
[shape {:keys [dx dy] :as opts}]
|
||||
(assoc shape
|
||||
:width width
|
||||
:height height))
|
||||
|
||||
(defmethod -resize :builtin/line
|
||||
[shape {:keys [width height] :as opts}]
|
||||
(throw (ex-info "Not implemented" {})))
|
||||
:x1 (+ (:x1 shape) dx)
|
||||
:y1 (+ (:y1 shape) dy)
|
||||
:x2 (+ (:x2 shape) dx)
|
||||
:y2 (+ (:y2 shape) dy)))
|
||||
|
||||
(defmethod -rotate ::shape
|
||||
[shape rotation]
|
||||
|
@ -129,8 +159,15 @@
|
|||
(assoc $ :y (+ (:y shape) (:dy group 0)))
|
||||
(container-rect $))))
|
||||
|
||||
(defmethod -outer-rect :builtin/line
|
||||
[shape]
|
||||
(let [{:keys [x1 y1 x2 y2]} shape
|
||||
props {:x x1 :y y1 :width (- x2 x1) :height (- y2 y1)}
|
||||
shape (merge shape props)]
|
||||
(container-rect shape)))
|
||||
|
||||
(defmethod -outer-rect :builtin/group
|
||||
[{:keys [id group rotation dx dy view-box] :as shape}]
|
||||
[{:keys [id group rotation dx dy] :as shape}]
|
||||
(let [shapes (->> (:items shape)
|
||||
(map #(get-in @st/state [:shapes-by-id %]))
|
||||
(map -outer-rect))
|
||||
|
|
|
@ -42,6 +42,12 @@
|
|||
(html
|
||||
[:g attrs data])))
|
||||
|
||||
(defmethod sh/-render :builtin/line
|
||||
[{:keys [id x1 y1 x2 y2]}]
|
||||
(html
|
||||
[:line {:x1 x1 :y1 y1 :x2 x2 :y2 y2
|
||||
:stroke "black"
|
||||
:stroke-width "1"}]))
|
||||
|
||||
;; FIXME: the impl should be more clear.
|
||||
|
||||
|
|
|
@ -14,11 +14,9 @@
|
|||
[uxbox.util.data :refer (parse-int parse-float)]))
|
||||
|
||||
(def +menus-map+
|
||||
{:builtin/icon [:menu/measures :menu/fill :menu/stroke]
|
||||
:builtin/rect [:menu/measures :menu/fill :menu/stroke]
|
||||
:builtin/circle [:menu/measures :menu/fill :menu/stroke]
|
||||
{:builtin/icon [:menu/icon-measures :menu/fill :menu/stroke]
|
||||
:builtin/line [:menu/stroke]
|
||||
:builtin/group [:menu/measures]})
|
||||
:builtin/group []})
|
||||
|
||||
(def +menus-by-id+
|
||||
{:menu/measures
|
||||
|
@ -44,8 +42,8 @@
|
|||
[new-x new-y]))
|
||||
|
||||
(defn- get-position
|
||||
[{:keys [page width] :as shape}]
|
||||
(let [{:keys [x y]} (sh/-outer-rect shape)
|
||||
[{:keys [page] :as shape}]
|
||||
(let [{:keys [x y width]} (sh/-outer-rect shape)
|
||||
vx (+ x width 50)
|
||||
vy (- y 50)]
|
||||
(viewportcoord->clientcoord page vx vy)))
|
||||
|
@ -162,26 +160,25 @@
|
|||
:step "0.0001"
|
||||
:on-change on-opacity-change}]]]])))
|
||||
|
||||
(defmethod -render-menu :menu/measures
|
||||
(defmethod -render-menu :menu/icon-measures
|
||||
[menu own shape]
|
||||
(letfn [(on-size-change [attr event]
|
||||
(let [value (dom/event->value event)
|
||||
value (parse-int value 0)
|
||||
sid (:id shape)]
|
||||
(-> (dw/update-shape-size sid {attr value})
|
||||
(rs/emit!))))
|
||||
sid (:id shape)
|
||||
props {attr value}]
|
||||
(rs/emit! (dw/update-shape-size sid props))))
|
||||
(on-rotation-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
value (parse-int value 0)
|
||||
sid (:id shape)]
|
||||
(-> (dw/update-shape-rotation sid value)
|
||||
(rs/emit!))))
|
||||
(rs/emit! (dw/update-shape-rotation sid value))))
|
||||
(on-pos-change [attr event]
|
||||
(let [value (dom/event->value event)
|
||||
value (parse-int value nil)
|
||||
sid (:id shape)]
|
||||
(-> (dw/update-shape-position sid {attr value})
|
||||
(rs/emit!))))]
|
||||
sid (:id shape)
|
||||
props {attr value}]
|
||||
(rs/emit! (dw/update-shape-position sid props))))]
|
||||
(html
|
||||
[:div.element-set {:key (str (:id menu))}
|
||||
[:div.element-set-title (:name menu)]
|
||||
|
@ -209,12 +206,12 @@
|
|||
{:placeholder "x"
|
||||
:type "number"
|
||||
:value (:x shape "")
|
||||
:on-change (partial on-pos-change :x)}]
|
||||
:on-change (partial on-pos-change :x1)}]
|
||||
[:input#width.input-text
|
||||
{:placeholder "y"
|
||||
:type "number"
|
||||
:value (:y shape "")
|
||||
:on-change (partial on-pos-change :y)}]]
|
||||
:on-change (partial on-pos-change :y1)}]]
|
||||
|
||||
[:span "Rotation"]
|
||||
[:div.row-flex
|
||||
|
@ -234,19 +231,20 @@
|
|||
zoom 1
|
||||
menus (get +menus-map+ (:type shape))
|
||||
active-menu (:menu @local (first menus))]
|
||||
(html
|
||||
[:div#element-options.element-options
|
||||
{:style {:left (* popup-x zoom) :top (- (* popup-y zoom) scroll)}}
|
||||
[:ul.element-icons
|
||||
(for [menu-id (get +menus-map+ (:type shape))
|
||||
:let [menu (get +menus-by-id+ menu-id)
|
||||
selected? (= active-menu menu-id)]]
|
||||
[:li#e-info {:on-click #(swap! local assoc :menu menu-id)
|
||||
:key (str "menu-" (:id menu))
|
||||
:class (when selected? "selected")}
|
||||
(:icon menu)])]
|
||||
(let [menu (get +menus-by-id+ active-menu)]
|
||||
(-render-menu menu own shape))])))
|
||||
(when (seq menus)
|
||||
(html
|
||||
[:div#element-options.element-options
|
||||
{:style {:left (* popup-x zoom) :top (- (* popup-y zoom) scroll)}}
|
||||
[:ul.element-icons
|
||||
(for [menu-id (get +menus-map+ (:type shape))
|
||||
:let [menu (get +menus-by-id+ menu-id)
|
||||
selected? (= active-menu menu-id)]]
|
||||
[:li#e-info {:on-click #(swap! local assoc :menu menu-id)
|
||||
:key (str "menu-" (:id menu))
|
||||
:class (when selected? "selected")}
|
||||
(:icon menu)])]
|
||||
(let [menu (get +menus-by-id+ active-menu)]
|
||||
(-render-menu menu own shape))]))))
|
||||
|
||||
(def ^:static element-opts
|
||||
(mx/component
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
[item]
|
||||
(case (:type item)
|
||||
:builtin/icon (shapes/-render-svg item)
|
||||
:builtin/line i/line
|
||||
:builtin/rect i/box
|
||||
:builtin/group i/folder))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue