From 56efb571be0e0250c386722bd573fcf197460b01 Mon Sep 17 00:00:00 2001 From: Eva Date: Mon, 7 Nov 2022 18:00:26 +0100 Subject: [PATCH] :sparkles: Add `add flex layout` option in context menu --- frontend/src/app/main/data/workspace.cljs | 34 +-------- .../app/main/data/workspace/selection.cljs | 4 +- .../app/main/data/workspace/shape_layout.cljs | 70 ++++++++++++++----- .../src/app/main/data/workspace/shapes.cljs | 44 ++++++++++-- .../data/workspace/shapes_update_layout.cljs | 28 ++++++++ .../app/main/data/workspace/shortcuts.cljs | 11 ++- .../app/main/ui/workspace/context_menu.cljs | 30 +++++++- frontend/translations/en.po | 8 +++ frontend/translations/es.po | 8 +++ 9 files changed, 177 insertions(+), 60 deletions(-) create mode 100644 frontend/src/app/main/data/workspace/shapes_update_layout.cljs diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index bedd710657..9b801f12ac 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -52,8 +52,8 @@ [app.main.data.workspace.path.shapes-to-path :as dwps] [app.main.data.workspace.persistence :as dwp] [app.main.data.workspace.selection :as dws] - [app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.shapes :as dwsh] + [app.main.data.workspace.shapes-update-layout :as dwul] [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.svg-upload :as svg] [app.main.data.workspace.thumbnails :as dwth] @@ -690,7 +690,7 @@ (rx/of (dch/commit-changes changes) (dwco/expand-collapse parent-id) - (dwsl/update-layout-positions [parent-id])))))) + (dwul/update-layout-positions [parent-id])))))) (defn relocate-selected-shapes [parent-id to-index] @@ -1571,36 +1571,6 @@ (rx/of (dch/commit-changes changes)))))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Artboard -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defn create-artboard-from-selection - [] - (ptk/reify ::create-artboard-from-selection - ptk/WatchEvent - (watch [_ state _] - (let [objects (wsh/lookup-page-objects state) - selected (wsh/lookup-selected state) - selected-objs (map #(get objects %) selected)] - (when (d/not-empty? selected) - (let [srect (gsh/selection-rect selected-objs) - frame-id (get-in objects [(first selected) :frame-id]) - parent-id (get-in objects [(first selected) :parent-id]) - shape (-> (cts/make-minimal-shape :frame) - (merge {:x (:x srect) :y (:y srect) :width (:width srect) :height (:height srect)}) - (assoc :frame-id frame-id :parent-id parent-id) - (cond-> (not= frame-id uuid/zero) - (assoc :fills [] :hide-in-viewer true)) - (cts/setup-rect-selrect))] - (rx/of - (dwu/start-undo-transaction) - (dwsh/add-shape shape) - (dwsh/move-shapes-into-frame (:id shape) selected) - - (dwu/commit-undo-transaction)))))))) - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Remove graphics ;; TODO: this should be deprecated and removed together with components-v2 diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 4d3dffaa7e..8791777c11 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -21,7 +21,7 @@ [app.main.data.modal :as md] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.collapse :as dwc] - [app.main.data.workspace.shape-layout :as dwsl] + [app.main.data.workspace.shapes-update-layout :as dwul] [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.thumbnails :as dwt] [app.main.data.workspace.zoom :as dwz] @@ -565,7 +565,7 @@ ;; Warning: This order is important for the focus mode. (rx/of (dch/commit-changes changes) (select-shapes new-selected) - (dwsl/update-layout-positions frames) + (dwul/update-layout-positions frames) (memorize-duplicated id-original id-duplicated)))))))))) (defn change-hover-state diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index 799cf0497c..7f2d7d3aec 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -8,10 +8,12 @@ (:require [app.common.data :as d] [app.common.pages.helpers :as cph] - [app.common.types.modifiers :as ctm] [app.common.types.shape.layout :as ctl] + [app.common.uuid :as uuid] [app.main.data.workspace.changes :as dwc] - [app.main.data.workspace.modifiers :as dwm] + [app.main.data.workspace.selection :as dwse] + [app.main.data.workspace.shapes :as dws] + [app.main.data.workspace.shapes-update-layout :as wsul] [app.main.data.workspace.state-helpers :as wsh] [beicon.core :as rx] [potok.core :as ptk])) @@ -44,19 +46,6 @@ (def initial-grid-layout ;; TODO {:layout :grid}) -(defn update-layout-positions - [ids] - (ptk/reify ::update-layout-positions - ptk/WatchEvent - (watch [_ state _] - (let [objects (wsh/lookup-page-objects state) - ids (->> ids (filter (partial ctl/layout? objects)))] - (if (d/not-empty? ids) - (let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))] - (rx/of (dwm/set-modifiers modif-tree) - (dwm/apply-modifiers))) - (rx/empty)))))) - (defn get-layout-initializer [type] (let [initial-layout-data (if (= type :flex) initial-flex-layout initial-grid-layout)] @@ -72,16 +61,59 @@ (let [objects (wsh/lookup-page-objects state) children-ids (into [] (mapcat #(get-in objects [% :shapes])) ids)] (rx/of (dwc/update-shapes ids (get-layout-initializer type)) - (update-layout-positions ids) + (wsul/update-layout-positions ids) (dwc/update-shapes children-ids #(dissoc % :constraints-h :constraints-v))))))) +(defn create-layout-from-selection + [type] + (ptk/reify ::create-layout-from-selection + ptk/WatchEvent + (watch [_ state _] + + (let [page-id (:current-page-id state) + objects (wsh/lookup-page-objects state page-id) + selected (wsh/lookup-selected state) + selected-shapes (map (d/getf objects) selected) + single? (= (count selected-shapes) 1) + has-group? (->> selected-shapes (d/seek cph/group-shape?)) + is-group? (and single? has-group?)] + (if is-group? + (let [parent-id (:parent-id (first selected-shapes)) + new-shape-id (uuid/next) + shapes-ids (:shapes (first selected-shapes)) + ordered-ids (into (d/ordered-set) shapes-ids)] + (rx/of (dwse/select-shapes ordered-ids) + (dws/create-artboard-from-selection new-shape-id parent-id) + (create-layout [new-shape-id] type) + (dws/delete-shapes page-id selected))) + + (let [new-shape-id (uuid/next)] + (rx/of (dws/create-artboard-from-selection new-shape-id) + (create-layout [new-shape-id] type)))))))) + (defn remove-layout [ids] (ptk/reify ::remove-layout ptk/WatchEvent (watch [_ _ _] (rx/of (dwc/update-shapes ids #(apply dissoc % layout-keys)) - (update-layout-positions ids))))) + (wsul/update-layout-positions ids))))) + +(defn toogle-layout-flex + [] + (ptk/reify ::toogle-layout-flex + ptk/WatchEvent + (watch [_ state _] + (let [page-id (:current-page-id state) + objects (wsh/lookup-page-objects state page-id) + selected (wsh/lookup-selected state) + selected-shapes (map (d/getf objects) selected) + single? (= (count selected-shapes) 1) + has-flex-layout? (and single? (= :flex (:layout (first selected-shapes))))] + + (if has-flex-layout? + (rx/of (remove-layout selected)) + (rx/of (create-layout-from-selection :flex))))))) (defn update-layout [ids changes] @@ -89,7 +121,7 @@ ptk/WatchEvent (watch [_ _ _] (rx/of (dwc/update-shapes ids #(d/deep-merge % changes)) - (update-layout-positions ids))))) + (wsul/update-layout-positions ids))))) (defn update-layout-child [ids changes] @@ -100,4 +132,4 @@ parent-ids (->> ids (map #(cph/get-parent-id objects %))) layout-ids (->> ids (filter (comp ctl/layout? (d/getf objects))))] (rx/of (dwc/update-shapes ids #(d/deep-merge (or % {}) changes)) - (update-layout-positions (d/concat-vec layout-ids parent-ids))))))) + (wsul/update-layout-positions (d/concat-vec layout-ids parent-ids))))))) diff --git a/frontend/src/app/main/data/workspace/shapes.cljs b/frontend/src/app/main/data/workspace/shapes.cljs index b36930d585..ee39ddc8df 100644 --- a/frontend/src/app/main/data/workspace/shapes.cljs +++ b/frontend/src/app/main/data/workspace/shapes.cljs @@ -9,6 +9,7 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.geom.proportions :as gpr] + [app.common.geom.shapes :as gsh] [app.common.pages.changes-builder :as pcb] [app.common.pages.helpers :as cph] [app.common.spec :as us] @@ -22,8 +23,9 @@ [app.main.data.workspace.changes :as dch] [app.main.data.workspace.edition :as dwe] [app.main.data.workspace.selection :as dws] - [app.main.data.workspace.shape-layout :as dwsl] + [app.main.data.workspace.shapes-update-layout :as dwsul] [app.main.data.workspace.state-helpers :as wsh] + [app.main.data.workspace.undo :as dwu] [app.main.features :as features] [app.main.streams :as ms] [beicon.core :as rx] @@ -102,7 +104,7 @@ (rx/concat (rx/of (dch/commit-changes changes) - (dwsl/update-layout-positions [(:parent-id shape)]) + (dwsul/update-layout-positions [(:parent-id shape)]) (when-not no-select? (dws/select-shapes (d/ordered-set id)))) (when (= :text (:type attrs)) @@ -270,9 +272,9 @@ (reduce ctp/remove-flow flows))))))] (rx/of (dc/detach-comment-thread ids) - (dwsl/update-layout-positions all-parents) + (dwsul/update-layout-positions all-parents) (dch/commit-changes changes) - (dwsl/update-layout-positions layout-ids))))))) + (dwsul/update-layout-positions layout-ids))))))) (defn- viewport-center [state] @@ -298,3 +300,37 @@ (assoc :frame-id frame-id) (cts/setup-rect-selrect))] (rx/of (add-shape shape)))))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Artboard +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn create-artboard-from-selection + ([] + (create-artboard-from-selection nil)) + ([id] + (create-artboard-from-selection id nil)) + ([id parent-id] + (ptk/reify ::create-artboard-from-selection + ptk/WatchEvent + (watch [_ state _] + (let [page-id (:current-page-id state) + objects (wsh/lookup-page-objects state page-id) + selected (wsh/lookup-selected state) + selected-objs (map #(get objects %) selected)] + (when (d/not-empty? selected) + (let [srect (gsh/selection-rect selected-objs) + frame-id (get-in objects [(first selected) :frame-id]) + parent-id (or parent-id (get-in objects [(first selected) :parent-id])) + shape (-> (cts/make-minimal-shape :frame) + (merge {:x (:x srect) :y (:y srect) :width (:width srect) :height (:height srect)}) + (cond-> id + (assoc :id id)) + (assoc :frame-id frame-id :parent-id parent-id) + (cond-> (not= frame-id uuid/zero) + (assoc :fills [] :hide-in-viewer true)) + (cts/setup-rect-selrect))] + (rx/of + (dwu/start-undo-transaction) + (add-shape shape) + (move-shapes-into-frame (:id shape) selected) + (dwu/commit-undo-transaction))))))))) diff --git a/frontend/src/app/main/data/workspace/shapes_update_layout.cljs b/frontend/src/app/main/data/workspace/shapes_update_layout.cljs new file mode 100644 index 0000000000..3274d23563 --- /dev/null +++ b/frontend/src/app/main/data/workspace/shapes_update_layout.cljs @@ -0,0 +1,28 @@ +;; 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) KALEIDOS INC + +(ns app.main.data.workspace.shapes-update-layout + (:require + [app.common.data :as d] + [app.common.types.modifiers :as ctm] + [app.common.types.shape.layout :as ctl] + [app.main.data.workspace.modifiers :as dwm] + [app.main.data.workspace.state-helpers :as wsh] + [beicon.core :as rx] + [potok.core :as ptk])) + +(defn update-layout-positions + [ids] + (ptk/reify ::update-layout-positions + ptk/WatchEvent + (watch [_ state _] + (let [objects (wsh/lookup-page-objects state) + ids (->> ids (filter (partial ctl/layout? objects)))] + (if (d/not-empty? ids) + (let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))] + (rx/of (dwm/set-modifiers modif-tree) + (dwm/apply-modifiers))) + (rx/empty)))))) diff --git a/frontend/src/app/main/data/workspace/shortcuts.cljs b/frontend/src/app/main/data/workspace/shortcuts.cljs index 4f2728d9f4..31fc056ee5 100644 --- a/frontend/src/app/main/data/workspace/shortcuts.cljs +++ b/frontend/src/app/main/data/workspace/shortcuts.cljs @@ -15,6 +15,8 @@ [app.main.data.workspace.drawing :as dwd] [app.main.data.workspace.layers :as dwly] [app.main.data.workspace.libraries :as dwl] + [app.main.data.workspace.shape-layout :as dwsl] + [app.main.data.workspace.shapes :as dws] [app.main.data.workspace.texts :as dwtxt] [app.main.data.workspace.transforms :as dwt] [app.main.data.workspace.undo :as dwu] @@ -204,7 +206,12 @@ :artboard-selection {:tooltip (ds/meta (ds/alt "G")) :command (ds/c-mod "alt+g") :subsections [:modify-layers] - :fn #(st/emit! (dw/create-artboard-from-selection))} + :fn #(st/emit! (dws/create-artboard-from-selection))} + + :toogle-layout-flex {:tooltip (ds/shift "F") + :command "shift+f" + :subsections [:modify-layers] + :fn #(st/emit! (dwsl/toogle-layout-flex))} ;; TOOLS @@ -382,7 +389,7 @@ :show-shortcuts {:tooltip "?" :command "?" :subsections [:main-menu] - :fn #(st/emit! (toggle-layout-flag :shortcuts)) } + :fn #(st/emit! (toggle-layout-flag :shortcuts))} ;; PANELS diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 39b8cfc10b..ab69b38794 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -19,6 +19,8 @@ [app.main.data.workspace.interactions :as dwi] [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.selection :as dws] + [app.main.data.workspace.shape-layout :as dwsl] + [app.main.data.workspace.shapes :as dwsh] [app.main.data.workspace.shortcuts :as sc] [app.main.features :as features] [app.main.refs :as refs] @@ -212,7 +214,7 @@ (let [multiple? (> (count shapes) 1) single? (= (count shapes) 1) - do-create-artboard-from-selection #(st/emit! (dw/create-artboard-from-selection)) + do-create-artboard-from-selection #(st/emit! (dwsh/create-artboard-from-selection)) has-frame? (->> shapes (d/seek cph/frame-shape?)) has-group? (->> shapes (d/seek cph/group-shape?)) @@ -364,6 +366,31 @@ [:& menu-entry {:title (tr "workspace.shape.menu.flow-start") :on-click do-add-flow}]))))) +(mf/defc context-menu-flex + [{:keys [shapes]}] + (let [single? (= (count shapes) 1) + has-frame? (->> shapes (d/seek cph/frame-shape?)) + is-frame? (and single? has-frame?) + is-flex-container? (and is-frame? (= :flex (:layout (first shapes)))) + has-group? (->> shapes (d/seek cph/group-shape?)) + is-group? (and single? has-group?) + ids (->> shapes (map :id)) + add-flex #(st/emit! (dwsl/create-layout-from-selection :flex)) + remove-flex #(st/emit! (dwsl/remove-layout ids))] + (cond + (or (not single?) (and is-frame? (not is-flex-container?)) is-group?) + [:* + [:& menu-separator] + [:& menu-entry {:title (tr "workspace.shape.menu.add-flex") + :shortcut (sc/get-tooltip :toogle-layout-flex) + :on-click add-flex}]] + + is-flex-container? + [:* + [:& menu-separator] + [:& menu-entry {:title (tr "workspace.shape.menu.remove-flex") + :shortcut (sc/get-tooltip :toogle-layout-flex) + :on-click remove-flex}]]))) (mf/defc context-menu-component [{:keys [shapes]}] @@ -517,6 +544,7 @@ [:> context-menu-path props] [:> context-menu-layer-options props] [:> context-menu-prototype props] + [:> context-menu-flex props] [:> context-menu-component props] [:> context-menu-delete props]]))) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 45cd4a44fe..ebf0fefaa0 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -4077,6 +4077,14 @@ msgstr "Update main components" msgid "workspace.shape.menu.update-main" msgstr "Update main component" +#: src/app/main/ui/workspace/context_menu.cljs +msgid "workspace.shape.menu.add-flex" +msgstr "Add layout flex" + +#: src/app/main/ui/workspace/context_menu.cljs +msgid "workspace.shape.menu.remove-flex" +msgstr "Remove layout flex" + msgid "workspace.sidebar.collapse" msgstr "Collapse sidebar" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 00a47ffed8..0e833ab0b3 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -4518,6 +4518,14 @@ msgstr "Actualizar componentes" msgid "workspace.shape.menu.update-main" msgstr "Actualizar componente principal" +#: src/app/main/ui/workspace/context_menu.cljs +msgid "workspace.shape.menu.add-flex" +msgstr "AƱadir layout flex" + +#: src/app/main/ui/workspace/context_menu.cljs +msgid "workspace.shape.menu.remove-flex" +msgstr "Eliminar layout flex" + msgid "workspace.sidebar.collapse" msgstr "Cerrar barra lateral"