mirror of
https://github.com/penpot/penpot.git
synced 2025-02-10 09:08:31 -05:00
🎉 Add resize constraints to shapes
This commit is contained in:
parent
55b0f6e950
commit
092a973f9a
9 changed files with 602 additions and 43 deletions
|
@ -188,6 +188,7 @@
|
|||
(d/export gpr/center->rect)
|
||||
|
||||
(d/export gtr/transform-shape)
|
||||
(d/export gtr/calc-child-modifiers)
|
||||
(d/export gtr/transform-matrix)
|
||||
(d/export gtr/inverse-transform-matrix)
|
||||
(d/export gtr/transform-point-center)
|
||||
|
|
|
@ -9,6 +9,11 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.common :as gco]))
|
||||
|
||||
(defn left-of [rect] (:x rect))
|
||||
(defn right-of [rect] (+ (:x rect) (:width rect)))
|
||||
(defn top-of [rect] (:y rect))
|
||||
(defn bottom-of [rect] (+ (:y rect) (:height rect)))
|
||||
|
||||
(defn rect->points [{:keys [x y width height]}]
|
||||
;; (assert (number? x))
|
||||
;; (assert (number? y))
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.common.geom.shapes.path :as gpa]
|
||||
[app.common.geom.shapes.rect :as gpr]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.spec :as spec]
|
||||
[app.common.text :as txt]))
|
||||
|
||||
;; --- Relative Movement
|
||||
|
@ -362,6 +363,138 @@
|
|||
(dissoc :modifiers)))
|
||||
shape))))
|
||||
|
||||
|
||||
(defn calc-child-modifiers
|
||||
[parent transformed-parent child parent-modifiers]
|
||||
(let [parent-rect (:selrect parent)
|
||||
transformed-parent-rect (:selrect transformed-parent)
|
||||
child-rect (:selrect child)
|
||||
|
||||
origin (:resize-origin parent-modifiers)
|
||||
|
||||
orig-h (when origin
|
||||
(cond
|
||||
(mth/close? (:x origin) (gpr/left-of parent-rect)) :left
|
||||
(mth/close? (:x origin) (gpr/right-of parent-rect)) :right
|
||||
:else :middle))
|
||||
|
||||
orig-v (when origin
|
||||
(cond
|
||||
(mth/close? (:y origin) (gpr/top-of parent-rect)) :top
|
||||
(mth/close? (:y origin) (gpr/bottom-of parent-rect)) :bottom
|
||||
:else :middle))
|
||||
|
||||
delta-h (when orig-h
|
||||
(cond (= orig-h :left)
|
||||
(- (gpr/right-of transformed-parent-rect) (gpr/right-of parent-rect))
|
||||
|
||||
(= orig-h :right)
|
||||
(- (gpr/left-of transformed-parent-rect) (gpr/left-of parent-rect))
|
||||
|
||||
:else 0))
|
||||
|
||||
delta-v (when orig-v
|
||||
(cond (= orig-v :top)
|
||||
(- (gpr/bottom-of transformed-parent-rect) (gpr/bottom-of parent-rect))
|
||||
|
||||
(= orig-v :bottom)
|
||||
(- (gpr/top-of transformed-parent-rect) (gpr/top-of parent-rect))
|
||||
|
||||
:else 0))
|
||||
|
||||
constraints-h (get child :constraints-h (spec/default-constraints-h child))
|
||||
constraints-v (get child :constraints-v (spec/default-constraints-v child))
|
||||
|
||||
modifiers-h (case constraints-h
|
||||
:left
|
||||
(if (= orig-h :right)
|
||||
{:displacement (gpt/point delta-h 0)} ;; we convert to matrix below
|
||||
{})
|
||||
|
||||
:right
|
||||
(if (= orig-h :left)
|
||||
{:displacement (gpt/point delta-h 0)}
|
||||
{})
|
||||
|
||||
:leftright
|
||||
(cond (= orig-h :left)
|
||||
{:resize-origin (gpt/point (gpr/left-of child-rect) (gpr/top-of child-rect))
|
||||
:resize-vector (gpt/point (/ (+ (:width child-rect) delta-h)
|
||||
(:width child-rect))
|
||||
1)}
|
||||
|
||||
(= orig-h :right)
|
||||
{:resize-origin (gpt/point (gpr/right-of child-rect) (gpr/top-of child-rect))
|
||||
:resize-vector (gpt/point (/ (- (:width child-rect) delta-h)
|
||||
(:width child-rect))
|
||||
1)}
|
||||
|
||||
:else {})
|
||||
|
||||
:center
|
||||
{:displacement (gpt/point (/ delta-h 2) 0)}
|
||||
|
||||
:scale
|
||||
(if (:resize-origin parent-modifiers)
|
||||
{:resize-origin (:resize-origin parent-modifiers)
|
||||
:resize-vector (gpt/point (:x (:resize-vector parent-modifiers)) 1)}
|
||||
{})
|
||||
|
||||
{})
|
||||
|
||||
modifiers-v (case constraints-v
|
||||
:top
|
||||
(if (= orig-v :bottom)
|
||||
{:displacement (gpt/point 0 delta-v)}
|
||||
{})
|
||||
|
||||
:bottom
|
||||
(if (= orig-v :top)
|
||||
{:displacement (gpt/point 0 delta-v)}
|
||||
{})
|
||||
|
||||
:topbottom
|
||||
(cond (= orig-v :top)
|
||||
{:resize-origin (gpt/point (gpr/left-of child-rect) (gpr/top-of child-rect))
|
||||
:resize-vector (gpt/point 1
|
||||
(/ (+ (:height child-rect) delta-v)
|
||||
(:height child-rect)))}
|
||||
|
||||
(= orig-v :bottom)
|
||||
{:resize-origin (gpt/point (gpr/left-of child-rect) (gpr/bottom-of child-rect))
|
||||
:resize-vector (gpt/point 1
|
||||
(/ (- (:height child-rect) delta-v)
|
||||
(:height child-rect)))}
|
||||
|
||||
:else {})
|
||||
|
||||
:center
|
||||
{:displacement (gpt/point 0 (/ delta-v 2))}
|
||||
|
||||
:scale
|
||||
(if (:resize-origin parent-modifiers)
|
||||
{:resize-origin (:resize-origin parent-modifiers)
|
||||
:resize-vector (gpt/point 1 (:y (:resize-vector parent-modifiers)))}
|
||||
{})
|
||||
|
||||
{})]
|
||||
|
||||
(cond-> {}
|
||||
(or (:displacement modifiers-h) (:displacement modifiers-v))
|
||||
(assoc :displacement (gmt/translate-matrix
|
||||
(gpt/point (get (:displacement modifiers-h) :x 0)
|
||||
(get (:displacement modifiers-v) :y 0))))
|
||||
|
||||
(or (:resize-vector modifiers-h) (:resize-vector modifiers-v))
|
||||
(assoc :resize-origin (or (:resize-origin modifiers-h) ;; we assume that the origin is the same
|
||||
(:resize-origin modifiers-v)) ;; in any direction
|
||||
:resize-vector (gpt/point (get (:resize-vector modifiers-h) :x 1)
|
||||
(get (:resize-vector modifiers-v) :y 1)))
|
||||
(:displacement parent-modifiers)
|
||||
(update :displacement #(if (nil? %)
|
||||
(:displacement parent-modifiers)
|
||||
(gmt/multiply % (:displacement parent-modifiers)))))))
|
||||
|
||||
(defn update-group-viewbox
|
||||
"Updates the viewbox for groups imported from SVG's"
|
||||
[{:keys [selrect svg-viewbox] :as group} new-selrect]
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; --- Specs
|
||||
|
@ -195,6 +196,30 @@
|
|||
(s/def :internal.shape/interactions
|
||||
(s/coll-of :internal.shape/interaction :kind vector?))
|
||||
|
||||
;; Size constraints
|
||||
|
||||
(s/def :internal.shape/constraints-h #{:left :right :leftright :center :scale})
|
||||
(s/def :internal.shape/constraints-v #{:top :bottom :topbottom :center :scale})
|
||||
(s/def :internal.shape/fixed-scroll boolean?)
|
||||
|
||||
; Shapes in the top frame have no constraints. Shapes directly below some
|
||||
; frame are left-top constrained. Else (shapes in a group) are scaled.
|
||||
(defn default-constraints-h
|
||||
[shape]
|
||||
(if (= (:parent-id shape) uuid/zero)
|
||||
nil
|
||||
(if (= (:parent-id shape) (:frame-id shape))
|
||||
:left
|
||||
:scale)))
|
||||
|
||||
(defn default-constraints-v
|
||||
[shape]
|
||||
(if (= (:parent-id shape) uuid/zero)
|
||||
nil
|
||||
(if (= (:parent-id shape) (:frame-id shape))
|
||||
:top
|
||||
:scale)))
|
||||
|
||||
;; Page Data related
|
||||
(s/def :internal.shape/blocked boolean?)
|
||||
(s/def :internal.shape/collapsed boolean?)
|
||||
|
@ -297,6 +322,9 @@
|
|||
:internal.shape/locked
|
||||
:internal.shape/proportion
|
||||
:internal.shape/proportion-lock
|
||||
:internal.shape/constraints-h
|
||||
:internal.shape/constraints-v
|
||||
:internal.shape/fixed-scroll
|
||||
:internal.shape/rx
|
||||
:internal.shape/ry
|
||||
:internal.shape/r1
|
||||
|
|
|
@ -1257,4 +1257,154 @@
|
|||
}
|
||||
}
|
||||
|
||||
.row-flex.align-top {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.constraints-widget {
|
||||
min-width: 72px;
|
||||
min-height: 72px;
|
||||
position: relative;
|
||||
background-color: $color-gray-60;
|
||||
flex-grow: 0;
|
||||
|
||||
.constraints-box {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
position: absolute;
|
||||
top: 22px;
|
||||
left: 22px;
|
||||
border: 2px solid $color-gray-50;
|
||||
}
|
||||
|
||||
.constraint-button {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
background-color: $color-gray-20;
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
&::after {
|
||||
background-color: $color-primary;
|
||||
}
|
||||
}
|
||||
|
||||
&.top,
|
||||
&.bottom {
|
||||
width: 28px;
|
||||
height: 22px;
|
||||
left: calc(50% - 14px);
|
||||
|
||||
&::after {
|
||||
width: 3px;
|
||||
height: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&.top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&.left,
|
||||
&.right {
|
||||
width: 22px;
|
||||
height: 28px;
|
||||
top: calc(50% - 14px);
|
||||
|
||||
&::after {
|
||||
width: 15px;
|
||||
height: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&.right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&.centerv {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
left: calc(50% - 14px);
|
||||
top: calc(50% - 14px);
|
||||
|
||||
&::after {
|
||||
width: 3px;
|
||||
height: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&.centerh {
|
||||
width: 28px;
|
||||
height: 15px;
|
||||
left: calc(50% - 14px);
|
||||
top: calc(50% - 7px);
|
||||
|
||||
&::after {
|
||||
width: 15px;
|
||||
height: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.constraints-form {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
|
||||
.input-select {
|
||||
font-size: $fs11;
|
||||
margin: 0 $x-small;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-left: $medium;
|
||||
fill: $color-gray-20;
|
||||
}
|
||||
|
||||
.left-right svg {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.top-down svg {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.fix-when {
|
||||
font-size: $fs11;
|
||||
cursor: pointer;
|
||||
|
||||
span {
|
||||
margin-left: $small;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
color: $color-primary;
|
||||
|
||||
svg {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -151,8 +151,7 @@
|
|||
:resize-origin origin
|
||||
:resize-transform shape-transform
|
||||
:resize-scale-text scale-text
|
||||
:resize-transform-inverse shape-transform-inverse}
|
||||
false))))
|
||||
:resize-transform-inverse shape-transform-inverse}))))
|
||||
|
||||
;; Unifies the instantaneous proportion lock modifier
|
||||
;; activated by Shift key and the shapes own proportion
|
||||
|
@ -426,10 +425,34 @@
|
|||
|
||||
;; -- Apply modifiers
|
||||
|
||||
(defn- set-modifiers-recursive
|
||||
[modif-tree objects shape modifiers]
|
||||
(let [children (->> (get shape :shapes [])
|
||||
(map #(get objects %)))
|
||||
|
||||
transformed-shape (when (seq children) ; <- don't calculate it if not needed
|
||||
(gsh/transform-shape
|
||||
(assoc shape :modifiers (select-keys modifiers
|
||||
[:resize-origin
|
||||
:resize-vector]))))
|
||||
|
||||
set-child (fn [modif-tree child]
|
||||
(let [child-modifiers (gsh/calc-child-modifiers shape
|
||||
transformed-shape
|
||||
child
|
||||
modifiers)]
|
||||
(set-modifiers-recursive modif-tree
|
||||
objects
|
||||
child
|
||||
child-modifiers)))]
|
||||
|
||||
(reduce set-child
|
||||
(update-in modif-tree [(:id shape) :modifiers] #(merge % modifiers))
|
||||
children)))
|
||||
|
||||
(defn set-modifiers
|
||||
([ids] (set-modifiers ids nil true))
|
||||
([ids modifiers] (set-modifiers ids modifiers true))
|
||||
([ids modifiers recurse-frames?]
|
||||
([ids] (set-modifiers ids nil))
|
||||
([ids modifiers]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(ptk/reify ::set-modifiers
|
||||
ptk/UpdateEvent
|
||||
|
@ -438,25 +461,16 @@
|
|||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
|
||||
ids (->> ids (into #{} (remove #(get-in objects [% :blocked] false))))
|
||||
|
||||
not-frame-id?
|
||||
(fn [shape-id]
|
||||
(let [shape (get objects shape-id)]
|
||||
(or recurse-frames? (not (= :frame (:type shape))))))
|
||||
|
||||
;; For each shape updates the modifiers given as arguments
|
||||
update-shape
|
||||
(fn [objects shape-id]
|
||||
(update-in objects [shape-id :modifiers] #(merge % modifiers)))
|
||||
|
||||
;; ID's + Children but remove frame children if the flag is set to false
|
||||
ids-with-children (concat ids (mapcat #(cp/get-children % objects)
|
||||
(filter not-frame-id? ids)))]
|
||||
|
||||
(update state :workspace-modifiers
|
||||
#(reduce update-shape % ids-with-children)))))))
|
||||
ids (->> ids (into #{} (remove #(get-in objects [% :blocked] false))))]
|
||||
|
||||
(reduce (fn [state id]
|
||||
(update state :workspace-modifiers
|
||||
#(set-modifiers-recursive %
|
||||
objects
|
||||
(get objects id)
|
||||
modifiers)))
|
||||
state
|
||||
ids))))))
|
||||
|
||||
;; Set-rotation is custom because applies different modifiers to each
|
||||
;; shape adjusting their position.
|
||||
|
@ -567,10 +581,7 @@
|
|||
(fn [objects shape-id]
|
||||
(let [shape (get objects shape-id)
|
||||
modifier (gsh/resize-modifiers shape attr value)]
|
||||
(-> objects
|
||||
(assoc-in [shape-id :modifiers] modifier)
|
||||
(cond-> (not (= :frame (:type shape)))
|
||||
(update-children (cp/get-children shape-id objects) modifier)))))]
|
||||
(set-modifiers-recursive objects objects shape modifier)))]
|
||||
|
||||
(d/update-in-when
|
||||
state
|
||||
|
@ -597,8 +608,7 @@
|
|||
(rx/of (set-modifiers selected
|
||||
{:resize-vector (gpt/point -1.0 1.0)
|
||||
:resize-origin origin
|
||||
:displacement (gmt/translate-matrix (gpt/point (- (:width selrect)) 0))}
|
||||
false)
|
||||
:displacement (gmt/translate-matrix (gpt/point (- (:width selrect)) 0))})
|
||||
(apply-modifiers selected))))))
|
||||
|
||||
(defn flip-vertical-selected []
|
||||
|
@ -614,8 +624,7 @@
|
|||
(rx/of (set-modifiers selected
|
||||
{:resize-vector (gpt/point 1.0 -1.0)
|
||||
:resize-origin origin
|
||||
:displacement (gmt/translate-matrix (gpt/point 0 (- (:height selrect))))}
|
||||
false)
|
||||
:displacement (gmt/translate-matrix (gpt/point 0 (- (:height selrect))))})
|
||||
(apply-modifiers selected))))))
|
||||
|
||||
(defn start-local-displacement [point]
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.measures
|
||||
(:require
|
||||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.store :as st]
|
||||
|
@ -15,12 +16,14 @@
|
|||
[app.util.data :refer [classnames]]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.pages.spec :as spec]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace :as udw]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
[app.common.math :as math]
|
||||
[app.util.i18n :refer [t] :as i18n]))
|
||||
[app.util.i18n :refer [tr] :as i18n]))
|
||||
|
||||
(def measure-attrs [:proportion-lock
|
||||
:width :height
|
||||
|
@ -28,7 +31,12 @@
|
|||
:rotation
|
||||
:rx :ry
|
||||
:r1 :r2 :r3 :r4
|
||||
:selrect])
|
||||
:selrect
|
||||
:constraints-h
|
||||
:constraints-v
|
||||
:fixed-scroll
|
||||
:parent-id
|
||||
:frame-id])
|
||||
|
||||
(defn- attr->string [attr values]
|
||||
(let [value (attr values)]
|
||||
|
@ -42,7 +50,6 @@
|
|||
(mf/defc measures-menu
|
||||
[{:keys [options ids ids-with-children values] :as props}]
|
||||
(let [options (or options #{:size :position :rotation :radius})
|
||||
locale (i18n/use-locale)
|
||||
|
||||
ids-with-children (or ids-with-children ids)
|
||||
|
||||
|
@ -65,6 +72,13 @@
|
|||
|
||||
proportion-lock (:proportion-lock values)
|
||||
|
||||
in-frame? (not= (:parent-id values) uuid/zero)
|
||||
first-level? (and in-frame?
|
||||
(= (:parent-id values) (:frame-id values)))
|
||||
|
||||
constraints-h (get values :constraints-h (spec/default-constraints-h values))
|
||||
constraints-v (get values :constraints-v (spec/default-constraints-v values))
|
||||
|
||||
on-size-change
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
|
@ -161,15 +175,75 @@
|
|||
on-radius-r2-change #(on-radius-4-change % :r2)
|
||||
on-radius-r3-change #(on-radius-4-change % :r3)
|
||||
on-radius-r4-change #(on-radius-4-change % :r4)
|
||||
select-all #(-> % (dom/get-target) (.select))]
|
||||
|
||||
select-all #(-> % (dom/get-target) (.select))
|
||||
|
||||
on-constraint-button-clicked
|
||||
(mf/use-callback
|
||||
(mf/deps [ids values])
|
||||
(fn [button]
|
||||
(fn [event]
|
||||
(let [constraints-h (get values :constraints-h :scale)
|
||||
constraints-v (get values :constraints-v :scale)
|
||||
|
||||
[constraint new-value]
|
||||
(case button
|
||||
:top (case constraints-v
|
||||
:top [:constraints-v :scale]
|
||||
:topbottom [:constraints-v :bottom]
|
||||
:bottom [:constraints-v :topbottom]
|
||||
[:constraints-v :top])
|
||||
:bottom (case constraints-v
|
||||
:bottom [:constraints-v :scale]
|
||||
:topbottom [:constraints-v :top]
|
||||
:top [:constraints-v :topbottom]
|
||||
[:constraints-v :bottom])
|
||||
:left (case constraints-h
|
||||
:left [:constraints-h :scale]
|
||||
:leftright [:constraints-h :right]
|
||||
:right [:constraints-h :leftright]
|
||||
[:constraints-h :left])
|
||||
:right (case constraints-h
|
||||
:right [:constraints-h :scale]
|
||||
:leftright [:constraints-h :left]
|
||||
:left [:constraints-h :leftright]
|
||||
[:constraints-h :right])
|
||||
:centerv (case constraints-v
|
||||
:center [:constraints-v :scale]
|
||||
[:constraints-v :center])
|
||||
:centerh (case constraints-h
|
||||
:center [:constraints-h :scale]
|
||||
[:constraints-h :center]))]
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc % constraint new-value)))))))
|
||||
|
||||
on-constraint-select-changed
|
||||
(mf/use-callback
|
||||
(mf/deps [ids values])
|
||||
(fn [constraint]
|
||||
(fn [event]
|
||||
(let [value (-> (dom/get-target-val event) (keyword))]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc % constraint value))))))))
|
||||
|
||||
on-fixed-scroll-clicked
|
||||
(mf/use-callback
|
||||
(mf/deps [ids values])
|
||||
(fn [event]
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(update % :fixed-scroll not)))))]
|
||||
[:*
|
||||
[:div.element-set
|
||||
[:div.element-set-content
|
||||
|
||||
;; WIDTH & HEIGHT
|
||||
(when (options :size)
|
||||
[:div.row-flex
|
||||
[:span.element-set-subtitle (t locale "workspace.options.size")]
|
||||
[:span.element-set-subtitle (tr "workspace.options.size")]
|
||||
[:div.input-element.width
|
||||
[:> numeric-input {:min 1
|
||||
:no-validate true
|
||||
|
@ -197,7 +271,7 @@
|
|||
;; POSITION
|
||||
(when (options :position)
|
||||
[:div.row-flex
|
||||
[:span.element-set-subtitle (t locale "workspace.options.position")]
|
||||
[:span.element-set-subtitle (tr "workspace.options.position")]
|
||||
[:div.input-element.Xaxis
|
||||
[:> numeric-input {:no-validate true
|
||||
:placeholder "--"
|
||||
|
@ -214,7 +288,7 @@
|
|||
;; ROTATION
|
||||
(when (options :rotation)
|
||||
[:div.row-flex
|
||||
[:span.element-set-subtitle (t locale "workspace.options.rotation")]
|
||||
[:span.element-set-subtitle (tr "workspace.options.rotation")]
|
||||
[:div.input-element.degrees
|
||||
[:> numeric-input
|
||||
{:no-validate true
|
||||
|
@ -244,14 +318,14 @@
|
|||
{:class (classnames
|
||||
:selected
|
||||
(and radius-1? (not radius-4?)))
|
||||
:alt (t locale "workspace.options.radius.all-corners")
|
||||
:alt (tr "workspace.options.radius.all-corners")
|
||||
:on-click on-switch-to-radius-1}
|
||||
i/radius-1]
|
||||
[:div.radius-icon.tooltip.tooltip-bottom
|
||||
{:class (classnames
|
||||
:selected
|
||||
(and radius-4? (not radius-1?)))
|
||||
:alt (t locale "workspace.options.radius.single-corners")
|
||||
:alt (tr "workspace.options.radius.single-corners")
|
||||
:on-click on-switch-to-radius-4}
|
||||
i/radius-4]]
|
||||
(if radius-1?
|
||||
|
@ -291,5 +365,68 @@
|
|||
:min 0
|
||||
:on-click select-all
|
||||
:on-change on-radius-r4-change
|
||||
:value (attr->string :r4 values)}]]])
|
||||
]))]]))
|
||||
:value (attr->string :r4 values)}]]])]))]]
|
||||
|
||||
;; CONSTRAINTS
|
||||
(when in-frame?
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.constraints")]]
|
||||
|
||||
[:div.element-set-content
|
||||
[:div.row-flex.align-top
|
||||
|
||||
[:div.constraints-widget
|
||||
[:div.constraints-box]
|
||||
[:div.constraint-button.top
|
||||
{:class (classnames :active (or (= constraints-v :top)
|
||||
(= constraints-v :topbottom)))
|
||||
:on-click (on-constraint-button-clicked :top)}]
|
||||
[:div.constraint-button.bottom
|
||||
{:class (classnames :active (or (= constraints-v :bottom)
|
||||
(= constraints-v :topbottom)))
|
||||
:on-click (on-constraint-button-clicked :bottom)}]
|
||||
[:div.constraint-button.left
|
||||
{:class (classnames :active (or (= constraints-h :left)
|
||||
(= constraints-h :leftright)))
|
||||
:on-click (on-constraint-button-clicked :left)}]
|
||||
[:div.constraint-button.right
|
||||
{:class (classnames :active (or (= constraints-h :right)
|
||||
(= constraints-h :leftright)))
|
||||
:on-click (on-constraint-button-clicked :right)}]
|
||||
[:div.constraint-button.centerv
|
||||
{:class (classnames :active (= constraints-v :center))
|
||||
:on-click (on-constraint-button-clicked :centerv)}]
|
||||
[:div.constraint-button.centerh
|
||||
{:class (classnames :active (= constraints-h :center))
|
||||
:on-click (on-constraint-button-clicked :centerh)}]]
|
||||
|
||||
[:div.constraints-form
|
||||
[:div.row-flex
|
||||
[:span.left-right i/full-screen]
|
||||
[:select.input-select {:on-change (on-constraint-select-changed :constraints-h)
|
||||
:value (d/name constraints-h "scale")}
|
||||
(when (= constraints-h :multiple)
|
||||
[:option {:value ""} (tr "settings.multiple")])
|
||||
[:option {:value "left"} (tr "workspace.options.constraints.left")]
|
||||
[:option {:value "right"} (tr "workspace.options.constraints.right")]
|
||||
[:option {:value "leftright"} (tr "workspace.options.constraints.leftright")]
|
||||
[:option {:value "center"} (tr "workspace.options.constraints.center")]
|
||||
[:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
|
||||
[:div.row-flex
|
||||
[:span.top-bottom i/full-screen]
|
||||
[:select.input-select {:on-change (on-constraint-select-changed :constraints-v)
|
||||
:value (d/name constraints-v "scale")}
|
||||
(when (= constraints-v :multiple)
|
||||
[:option {:value ""} (tr "settings.multiple")])
|
||||
[:option {:value "top"} (tr "workspace.options.constraints.top")]
|
||||
[:option {:value "bottom"} (tr "workspace.options.constraints.bottom")]
|
||||
[:option {:value "topbottom"} (tr "workspace.options.constraints.topbottom")]
|
||||
[:option {:value "center"} (tr "workspace.options.constraints.center")]
|
||||
[:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
|
||||
(when first-level?
|
||||
[:div.row-flex
|
||||
[:div.fix-when {:class (classnames :active (:fixed-scroll values))
|
||||
:on-click on-fixed-scroll-clicked}
|
||||
i/pin
|
||||
[:span (tr "workspace.options.constraints.fix-when-scrolling")]]])]]]])]))
|
||||
|
|
|
@ -1884,6 +1884,54 @@ msgstr "Canvas background"
|
|||
msgid "workspace.options.component"
|
||||
msgstr "Component"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints"
|
||||
msgstr "Constraints"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.left"
|
||||
msgstr "Left"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.right"
|
||||
msgstr "Right"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.leftright"
|
||||
msgstr "Left & Right"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.center"
|
||||
msgstr "Center"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.scale"
|
||||
msgstr "Scale"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.top"
|
||||
msgstr "Top"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.bottom"
|
||||
msgstr "Bottom"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.topbottom"
|
||||
msgstr "Top & Bottom"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.center"
|
||||
msgstr "Center"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.scale"
|
||||
msgstr "Scale"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.fix-when-scrolling"
|
||||
msgstr "Fix when scrolling"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options.cljs
|
||||
msgid "workspace.options.design"
|
||||
msgstr "Design"
|
||||
|
|
|
@ -1876,6 +1876,54 @@ msgstr "Color de fondo"
|
|||
msgid "workspace.options.component"
|
||||
msgstr "Componente"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints"
|
||||
msgstr "Restricciones"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.left"
|
||||
msgstr "Izquierda"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.right"
|
||||
msgstr "Derecha"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.leftright"
|
||||
msgstr "Izq. y Der."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.center"
|
||||
msgstr "Centro"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.scale"
|
||||
msgstr "Escalar"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.top"
|
||||
msgstr "Arriba"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.bottom"
|
||||
msgstr "Abajo"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.topbottom"
|
||||
msgstr "Arriba y Abajo"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.center"
|
||||
msgstr "Centro"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.scale"
|
||||
msgstr "Escalar"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs
|
||||
msgid "workspace.options.constraints.fix-when-scrolling"
|
||||
msgstr "Fijo al desplazar"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options.cljs
|
||||
msgid "workspace.options.design"
|
||||
msgstr "Diseño"
|
||||
|
|
Loading…
Add table
Reference in a new issue