diff --git a/common/src/app/common/types/interactions.cljc b/common/src/app/common/types/interactions.cljc
index 287b4b30d..aa28a6425 100644
--- a/common/src/app/common/types/interactions.cljc
+++ b/common/src/app/common/types/interactions.cljc
@@ -45,6 +45,14 @@
:open-url})
(s/def ::destination (s/nilable ::us/uuid))
+(s/def ::overlay-pos-type #{:manual
+ :center
+ :top-left
+ :top-right
+ :top-center
+ :bottom-left
+ :bottom-right
+ :bottom-center})
(s/def ::overlay-position ::point)
(s/def ::url ::us/string)
@@ -55,7 +63,8 @@
(defmethod action-opts-spec :open-overlay [_]
(s/keys :req-un [::destination
- ::overlay-position]))
+ ::overlay-position
+ ::overlay-pos-type]))
(defmethod action-opts-spec :close-overlay [_]
(s/keys :req-un [::destination]))
@@ -92,6 +101,8 @@
;; -- Helpers
+(declare calc-overlay-position)
+
(defn set-event-type
[interaction event-type]
(us/verify ::interaction interaction)
@@ -110,7 +121,7 @@
(defn set-action-type
- [interaction action-type]
+ [interaction action-type shape objects]
(us/verify ::interaction interaction)
(us/verify ::action-type action-type)
(if (= (:action-type interaction) action-type)
@@ -123,10 +134,21 @@
:destination (get interaction :destination))
:open-overlay
- (assoc interaction
- :action-type action-type
- :destination (get interaction :destination)
- :overlay-position (get interaction :overlay-position (gpt/point 0 0)))
+ (let [destination (get interaction :destination)
+ overlay-pos-type (get interaction :overlay-pos-type :center)
+ overlay-position (get interaction
+ :overlay-position
+ (calc-overlay-position
+ destination
+ interaction
+ shape
+ objects
+ overlay-pos-type))]
+ (assoc interaction
+ :action-type action-type
+ :destination destination
+ :overlay-pos-type overlay-pos-type
+ :overlay-position overlay-position))
:close-overlay
(assoc interaction
@@ -142,7 +164,6 @@
:action-type action-type
:url (get interaction :url "")))))
-
(defn set-destination
[interaction destination shape objects]
(us/verify ::interaction interaction)
@@ -150,33 +171,95 @@
(assert (or (nil? destination)
(some? (get objects destination))))
(assert #(:navigate :open-overlay :close-overlay) (:action-type interaction))
- (let [calc-overlay-position
- (fn []
- (if (nil? destination)
- (gpt/point 0 0)
- (let [dest-frame (get objects destination)
- overlay-size (:selrect dest-frame)
+ (cond-> interaction
+ :always
+ (assoc :destination destination)
- orig-frame (if (= (:type shape) :frame)
- shape
- (get objects (:frame-id shape)))
- frame-size (:selrect orig-frame)
+ (= (:action-type interaction) :open-overlay)
+ (assoc :overlay-pos-type :center
+ :overlay-position (calc-overlay-position destination
+ interaction
+ shape
+ objects
+ :center))))
- x (/ (- (:width frame-size) (:width overlay-size)) 2)
- y (/ (- (:height frame-size) (:height overlay-size)) 2)]
- (gpt/point x y))))]
-
- (cond-> interaction
- :always
- (assoc :destination destination)
-
- (= (:action-type interaction) :open-overlay)
- (assoc :overlay-position (calc-overlay-position)))))
+(defn set-overlay-pos-type
+ [interaction overlay-pos-type shape objects]
+ (us/verify ::interaction interaction)
+ (us/verify ::overlay-pos-type overlay-pos-type)
+ (assert #(= :open-overlay (:action-type interaction)))
+ (assoc interaction
+ :overlay-pos-type overlay-pos-type
+ :overlay-position (calc-overlay-position (:destination interaction)
+ interaction
+ shape
+ objects
+ overlay-pos-type)))
+(defn toggle-overlay-pos-type
+ [interaction overlay-pos-type shape objects]
+ (us/verify ::interaction interaction)
+ (us/verify ::overlay-pos-type overlay-pos-type)
+ (assert #(= :open-overlay (:action-type interaction)))
+ (let [new-pos-type (if (= (:overlay-pos-type interaction) overlay-pos-type)
+ :manual
+ overlay-pos-type)]
+ (assoc interaction
+ :overlay-pos-type new-pos-type
+ :overlay-position (calc-overlay-position (:destination interaction)
+ interaction
+ shape
+ objects
+ new-pos-type))))
(defn set-overlay-position
[interaction overlay-position]
(us/verify ::interaction interaction)
(us/verify ::overlay-position overlay-position)
- (assoc interaction :overlay-position overlay-position))
+ (assert #(= :open-overlay (:action-type interaction)))
+ (assoc interaction
+ :overlay-pos-type :manual
+ :overlay-position overlay-position))
+
+(defn- calc-overlay-position
+ [destination interaction shape objects overlay-pos-type]
+ (if (nil? destination)
+ (gpt/point 0 0)
+ (let [dest-frame (get objects destination)
+ overlay-size (:selrect dest-frame)
+ orig-frame (if (= (:type shape) :frame)
+ shape
+ (get objects (:frame-id shape)))
+ frame-size (:selrect orig-frame)]
+ (case overlay-pos-type
+
+ :center
+ (gpt/point (/ (- (:width frame-size) (:width overlay-size)) 2)
+ (/ (- (:height frame-size) (:height overlay-size)) 2))
+
+ :top-left
+ (gpt/point 0 0)
+
+ :top-right
+ (gpt/point (- (:width frame-size) (:width overlay-size))
+ 0)
+
+ :top-center
+ (gpt/point (/ (- (:width frame-size) (:width overlay-size)) 2)
+ 0)
+
+ :bottom-left
+ (gpt/point 0
+ (- (:height frame-size) (:height overlay-size)))
+
+ :bottom-right
+ (gpt/point (- (:width frame-size) (:width overlay-size))
+ (- (:height frame-size) (:height overlay-size)))
+
+ :bottom-center
+ (gpt/point (/ (- (:width frame-size) (:width overlay-size)) 2)
+ (- (:height frame-size) (:height overlay-size)))
+
+ :manual
+ (:overlay-position interaction)))))
diff --git a/frontend/resources/images/icons/position-bottom-center.svg b/frontend/resources/images/icons/position-bottom-center.svg
new file mode 100644
index 000000000..002466ead
--- /dev/null
+++ b/frontend/resources/images/icons/position-bottom-center.svg
@@ -0,0 +1,6 @@
+
diff --git a/frontend/resources/images/icons/position-bottom-left.svg b/frontend/resources/images/icons/position-bottom-left.svg
new file mode 100644
index 000000000..4811b74a9
--- /dev/null
+++ b/frontend/resources/images/icons/position-bottom-left.svg
@@ -0,0 +1,6 @@
+
diff --git a/frontend/resources/images/icons/position-bottom-right.svg b/frontend/resources/images/icons/position-bottom-right.svg
new file mode 100644
index 000000000..ebf861dcf
--- /dev/null
+++ b/frontend/resources/images/icons/position-bottom-right.svg
@@ -0,0 +1,6 @@
+
diff --git a/frontend/resources/images/icons/position-center.svg b/frontend/resources/images/icons/position-center.svg
new file mode 100644
index 000000000..ce6695ba7
--- /dev/null
+++ b/frontend/resources/images/icons/position-center.svg
@@ -0,0 +1,6 @@
+
diff --git a/frontend/resources/images/icons/position-top-center.svg b/frontend/resources/images/icons/position-top-center.svg
new file mode 100644
index 000000000..5a971d427
--- /dev/null
+++ b/frontend/resources/images/icons/position-top-center.svg
@@ -0,0 +1,6 @@
+
diff --git a/frontend/resources/images/icons/position-top-left.svg b/frontend/resources/images/icons/position-top-left.svg
new file mode 100644
index 000000000..0285e444e
--- /dev/null
+++ b/frontend/resources/images/icons/position-top-left.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/frontend/resources/images/icons/position-top-right.svg b/frontend/resources/images/icons/position-top-right.svg
new file mode 100644
index 000000000..838f63602
--- /dev/null
+++ b/frontend/resources/images/icons/position-top-right.svg
@@ -0,0 +1,6 @@
+
diff --git a/frontend/resources/styles/main/partials/sidebar-element-options.scss b/frontend/resources/styles/main/partials/sidebar-element-options.scss
index f1845e3d9..5eee36b8d 100644
--- a/frontend/resources/styles/main/partials/sidebar-element-options.scss
+++ b/frontend/resources/styles/main/partials/sidebar-element-options.scss
@@ -945,11 +945,15 @@
width: 12px;
height: 12px;
fill: $color-gray-20;
+ stroke: $color-gray-20;
}
- &:hover svg {
+ &:hover svg,
+ &.active svg {
fill: $color-primary;
+ stroke: $color-primary;
}
+
&.actions-inside {
position: absolute;
right: 0;
diff --git a/frontend/resources/styles/main/partials/sidebar-interactions.scss b/frontend/resources/styles/main/partials/sidebar-interactions.scss
index c8ea87266..d2c9cb1dc 100644
--- a/frontend/resources/styles/main/partials/sidebar-interactions.scss
+++ b/frontend/resources/styles/main/partials/sidebar-interactions.scss
@@ -47,3 +47,13 @@
width: 64px;
}
}
+
+.interactions-pos-buttons {
+ margin-top: $small;
+ justify-content: space-around;
+
+ svg {
+ width: 18px;
+ height: 18px;
+ }
+}
diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs
index dbff3982c..a53fdcee3 100644
--- a/frontend/src/app/main/data/workspace.cljs
+++ b/frontend/src/app/main/data/workspace.cljs
@@ -1827,8 +1827,8 @@
frame)]
;; Update or create interaction
(if index
- (update-in interactions [index]
- #(cti/set-destination % (:id frame) shape objects))
+ (update interactions index
+ #(cti/set-destination % (:id frame) shape objects))
(conj (or interactions [])
(cti/set-destination cti/default-interaction
(:id frame)
@@ -1870,11 +1870,11 @@
(rx/concat
(->> ms/mouse-position
(rx/take-until stopper)
- (rx/map #(move-overlay-pos % overlay-pos frame-pos offset)))
- (rx/of (finish-move-overlay-pos index overlay-pos frame-pos offset)))))))))
+ (rx/map #(move-overlay-pos % frame-pos offset)))
+ (rx/of (finish-move-overlay-pos index frame-pos offset)))))))))
(defn move-overlay-pos
- [pos overlay-pos frame-pos offset]
+ [pos frame-pos offset]
(ptk/reify ::move-overlay-pos
ptk/UpdateEvent
(update [_ state]
@@ -1884,7 +1884,7 @@
(assoc-in state [:workspace-local :move-overlay-to] pos)))))
(defn finish-move-overlay-pos
- [index overlay-pos frame-pos offset]
+ [index frame-pos offset]
(ptk/reify ::finish-move-overlay-pos
ptk/UpdateEvent
(update [_ state]
diff --git a/frontend/src/app/main/ui/icons.cljs b/frontend/src/app/main/ui/icons.cljs
index 47738e45a..abf60ef6e 100644
--- a/frontend/src/app/main/ui/icons.cljs
+++ b/frontend/src/app/main/ui/icons.cljs
@@ -101,6 +101,13 @@
(def play (icon-xref :play))
(def plus (icon-xref :plus))
(def pointer-inner (icon-xref :pointer-inner))
+(def position-bottom-center (icon-xref :position-bottom-center))
+(def position-bottom-left (icon-xref :position-bottom-left))
+(def position-bottom-right (icon-xref :position-bottom-right))
+(def position-center (icon-xref :position-center))
+(def position-top-center (icon-xref :position-top-center))
+(def position-top-left (icon-xref :position-top-left))
+(def position-top-right (icon-xref :position-top-right))
(def radius (icon-xref :radius))
(def radius-1 (icon-xref :radius-1))
(def radius-4 (icon-xref :radius-4))
diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs
index b55016671..99fa30d33 100644
--- a/frontend/src/app/main/ui/viewer.cljs
+++ b/frontend/src/app/main/ui/viewer.cljs
@@ -146,8 +146,8 @@
{:style {:width (:width size-over)
:height (:height size-over)
:position "absolute"
- :left (:x (:position overlay))
- :top (:y (:position overlay))}}
+ :left (* (:x (:position overlay)) zoom)
+ :top (* (:y (:position overlay)) zoom)}}
[:& interactions/viewport
{:frame (:frame overlay)
:size size-over
diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
index c8dc7c2e7..3bdd854d1 100644
--- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
@@ -31,7 +31,8 @@
[]
{:navigate (tr "workspace.options.interaction-navigate-to")
:open-overlay (tr "workspace.options.interaction-open-overlay")
- :close-overlay (tr "workspace.options.interaction-close-overlay")})
+ :close-overlay (tr "workspace.options.interaction-close-overlay")
+ :prev-screen (tr "workspace.options.interaction-prev-screen")})
(defn- action-summary
[interaction destination]
@@ -44,6 +45,17 @@
(get destination :name (tr "workspace.options.interaction-self")))
"--"))
+(defn- overlay-pos-type-names
+ []
+ {:manual (tr "workspace.options.interaction-pos-manual")
+ :center (tr "workspace.options.interaction-pos-center")
+ :top-left (tr "workspace.options.interaction-pos-top-left")
+ :top-right (tr "workspace.options.interaction-pos-top-right")
+ :top-center (tr "workspace.options.interaction-pos-top-center")
+ :bottom-left (tr "workspace.options.interaction-pos-bottom-left")
+ :bottom-right (tr "workspace.options.interaction-pos-bottom-right")
+ :bottom-center (tr "workspace.options.interaction-pos-bottom-center")})
+
(mf/defc interaction-entry
[{:keys [index shape interaction update-interaction remove-interaction]}]
(let [objects (deref refs/workspace-page-objects)
@@ -51,6 +63,9 @@
frames (mf/use-memo (mf/deps objects)
#(cp/select-frames objects))
+ action-type (:action-type interaction)
+ overlay-pos-type (:overlay-pos-type interaction)
+
extended-open? (mf/use-state false)
change-event-type
@@ -61,13 +76,22 @@
change-action-type
(fn [event]
(let [value (-> event dom/get-target dom/get-value d/read-string)]
- (update-interaction index #(cti/set-action-type % value))))
+ (update-interaction index #(cti/set-action-type % value shape objects))))
change-destination
(fn [event]
(let [value (-> event dom/get-target dom/get-value)
value (when (not= value "") (uuid/uuid value))]
- (update-interaction index #(cti/set-destination % value shape objects))))]
+ (update-interaction index #(cti/set-destination % value shape objects))))
+
+ change-overlay-pos-type
+ (fn [event]
+ (let [value (-> event dom/get-target dom/get-value d/read-string)]
+ (update-interaction index #(cti/set-overlay-pos-type % value shape objects))))
+
+ toggle-overlay-pos-type
+ (fn [pos-type]
+ (update-interaction index #(cti/toggle-overlay-pos-type % pos-type shape objects)))]
[:*
[:div.element-set-options-group
@@ -95,7 +119,8 @@
:on-change change-action-type}
(for [[value name] (action-type-names)]
[:option {:value (str value)} name])]]
- [:div.interactions-element
+ (when (#{:navigate :open-overlay :close-overlay} action-type)
+ [:div.interactions-element
[:span.element-set-subtitle.wide (tr "workspace.options.interaction-destination")]
[:select.input-select
{:value (str (:destination interaction))
@@ -104,7 +129,45 @@
(for [frame frames]
(when (and (not= (:id frame) (:id shape)) ; A frame cannot navigate to itself
(not= (:id frame) (:frame-id shape))) ; nor a shape to its container frame
- [:option {:value (str (:id frame))} (:name frame)]))]]]])]))
+ [:option {:value (str (:id frame))} (:name frame)]))]])
+ (when (= action-type :open-overlay)
+ [:*
+ [:div.interactions-element
+ [:span.element-set-subtitle.wide (tr "workspace.options.interaction-position")]
+ [:select.input-select
+ {:value (str (:overlay-pos-type interaction))
+ :on-change change-overlay-pos-type}
+ (for [[value name] (overlay-pos-type-names)]
+ [:option {:value (str value)} name])]]
+ [:div.interactions-element.interactions-pos-buttons
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :center))
+ :on-click #(toggle-overlay-pos-type :center)}
+ i/position-center]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :top-left))
+ :on-click #(toggle-overlay-pos-type :top-left)}
+ i/position-top-left]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :top-right))
+ :on-click #(toggle-overlay-pos-type :top-right)}
+ i/position-top-right]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :top-center))
+ :on-click #(toggle-overlay-pos-type :top-center)}
+ i/position-top-center]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :bottom-left))
+ :on-click #(toggle-overlay-pos-type :bottom-left)}
+ i/position-bottom-left]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :bottom-right))
+ :on-click #(toggle-overlay-pos-type :bottom-right)}
+ i/position-bottom-right]
+ [:div.element-set-actions-button
+ {:class (dom/classnames :active (= overlay-pos-type :bottom-center))
+ :on-click #(toggle-overlay-pos-type :bottom-center)}
+ i/position-bottom-center]]])]])]))
(mf/defc interactions-menu
[{:keys [shape] :as props}]
diff --git a/frontend/src/app/main/ui/workspace/viewport/interactions.cljs b/frontend/src/app/main/ui/workspace/viewport/interactions.cljs
index 404431856..a5ec3e378 100644
--- a/frontend/src/app/main/ui/workspace/viewport/interactions.cljs
+++ b/frontend/src/app/main/ui/workspace/viewport/interactions.cljs
@@ -194,9 +194,9 @@
(mf/defc overlay-marker
- [{:keys [index orig-shape dest-shape position objects zoom] :as props}]
+ [{:keys [index orig-shape dest-shape position objects] :as props}]
(let [start-move-position
- (fn [event]
+ (fn [_]
(st/emit! (dw/start-move-overlay-pos index)))]
(when dest-shape
@@ -287,15 +287,13 @@
:orig-shape shape
:dest-shape dest-shape
:position move-overlay-to
- :objects objects
- :zoom zoom}]
+ :objects objects}]
[:& overlay-marker {:key (str "pos" (:id shape) "-" index)
:index index
:orig-shape shape
:dest-shape dest-shape
:position (:overlay-position interaction)
- :objects objects
- :zoom zoom}]))])))
+ :objects objects}]))])))
(when (not (#{:move :rotate} current-transform))
[:& interaction-handle {:key (:id shape)
:index nil
diff --git a/frontend/translations/en.po b/frontend/translations/en.po
index 0ed54d467..a49fdf5a1 100644
--- a/frontend/translations/en.po
+++ b/frontend/translations/en.po
@@ -2441,6 +2441,42 @@ msgstr "Open overlay"
msgid "workspace.options.interaction-open-overlay-dest"
msgstr "Open overlay: %s"
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-manual"
+msgstr "Manual"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-center"
+msgstr "Center"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-top-left"
+msgstr "Top left"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-top-right"
+msgstr "Top right"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-top-center"
+msgstr "Top center"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-bottom-left"
+msgstr "Bottom left"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-bottom-right"
+msgstr "Bottom right"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-bottom-center"
+msgstr "Bottom center"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-position"
+msgstr "Position"
+
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-self"
msgstr "self"
diff --git a/frontend/translations/es.po b/frontend/translations/es.po
index 83b47aefe..1e48f671a 100644
--- a/frontend/translations/es.po
+++ b/frontend/translations/es.po
@@ -2324,6 +2324,42 @@ msgstr "Open overlay"
msgid "workspace.options.interaction-open-overlay-dest"
msgstr "Open overlay: %s"
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-manual"
+msgstr "Manual"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-center"
+msgstr "Centro"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-top-left"
+msgstr "Arriba izquierda"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-top-right"
+msgstr "Arriba derecha"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-top-center"
+msgstr "Arriba centro"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-bottom-left"
+msgstr "Abajo izquierda"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-bottom-right"
+msgstr "Abajo derecha"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-pos-bottom-center"
+msgstr "Abajo centro"
+
+#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
+msgid "workspace.options.interaction-position"
+msgstr "PosiciĆ³n"
+
#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs
msgid "workspace.options.interaction-self"
msgstr "self"