diff --git a/src/actions/action.ts b/src/actions/action.ts index 7ccffbef52..a4a4ba9e68 100644 --- a/src/actions/action.ts +++ b/src/actions/action.ts @@ -1,4 +1,5 @@ import { isMacOS } from "../components/helpers/dom_helpers"; +import { Model } from "../model"; import { Color } from "../types/misc"; import { SpreadsheetChildEnv } from "../types/spreadsheet_env"; @@ -13,8 +14,8 @@ export interface ActionSpec { /** * String or a function to compute the name */ - name: string | ((env: SpreadsheetChildEnv) => string); - description?: string | ((env: SpreadsheetChildEnv) => string); + name: string | ((model: Model, env: SpreadsheetChildEnv) => string); + description?: string | ((model: Model, env: SpreadsheetChildEnv) => string); shortcut?: string; /** * which represents its position inside the @@ -28,24 +29,24 @@ export interface ActionSpec { /** * Can be defined to compute the visibility of the item */ - isVisible?: (env: SpreadsheetChildEnv) => boolean; + isVisible?: (model: Model, env: SpreadsheetChildEnv) => boolean; /** * Can be defined to compute if the user can click on the action */ - isEnabled?: (env: SpreadsheetChildEnv) => boolean; + isEnabled?: (model: Model, env: SpreadsheetChildEnv) => boolean; /** * Can be defined to compute if the action is active */ - isActive?: (env: SpreadsheetChildEnv) => boolean; + isActive?: (model: Model, env: SpreadsheetChildEnv) => boolean; /** * Can be defined to display an icon */ - icon?: string | ((env: SpreadsheetChildEnv) => string); + icon?: string | ((model: Model, env: SpreadsheetChildEnv) => string); iconColor?: Color; /** * Can be defined to display another icon on the right of the item. */ - secondaryIcon?: string | ((env: SpreadsheetChildEnv) => string); + secondaryIcon?: string | ((model: Model, env: SpreadsheetChildEnv) => string); /** * is the action allowed when running spreadsheet in readonly mode */ @@ -59,7 +60,7 @@ export interface ActionSpec { * Execute the action. The action can return a result. * The result will be carried by a `menu-clicked` event to the menu parent component. */ - execute?: (env: SpreadsheetChildEnv, isMiddleClick?: boolean) => unknown; + execute?: (model: Model, env: SpreadsheetChildEnv, isMiddleClick?: boolean) => unknown; /** * subitems associated to this item * NB: an action without an execute function or children is not displayed ! @@ -71,30 +72,30 @@ export interface ActionSpec { */ separator?: boolean; textColor?: Color; - onStartHover?: (env: SpreadsheetChildEnv) => void; - onStopHover?: (env: SpreadsheetChildEnv) => void; + onStartHover?: (model: Model, env: SpreadsheetChildEnv) => void; + onStopHover?: (model: Model, env: SpreadsheetChildEnv) => void; } export interface Action { - name: (env: SpreadsheetChildEnv) => string; - description: (env: SpreadsheetChildEnv) => string; + name: (model: Model, env: SpreadsheetChildEnv) => string; + description: (model: Model, env: SpreadsheetChildEnv) => string; shortcut: string; sequence: number; id: string; - isVisible: (env: SpreadsheetChildEnv) => boolean; - isEnabled: (env: SpreadsheetChildEnv) => boolean; - isActive?: (env: SpreadsheetChildEnv) => boolean; - icon: (env: SpreadsheetChildEnv) => string; + isVisible: (model: Model, env: SpreadsheetChildEnv) => boolean; + isEnabled: (model: Model, env: SpreadsheetChildEnv) => boolean; + isActive?: (model: Model, env: SpreadsheetChildEnv) => boolean; + icon: (model: Model, env: SpreadsheetChildEnv) => string; iconColor?: Color; - secondaryIcon: (env: SpreadsheetChildEnv) => string; + secondaryIcon: (model: Model, env: SpreadsheetChildEnv) => string; isReadonlyAllowed: boolean; isEnabledOnLockedSheet: boolean; - execute?: (env: SpreadsheetChildEnv, isMiddleClick?: boolean) => unknown; - children: (env: SpreadsheetChildEnv) => Action[]; + execute?: (model: Model, env: SpreadsheetChildEnv, isMiddleClick?: boolean) => unknown; + children: (model: Model, env: SpreadsheetChildEnv) => Action[]; separator: boolean; textColor?: Color; - onStartHover?: (env: SpreadsheetChildEnv) => void; - onStopHover?: (env: SpreadsheetChildEnv) => void; + onStartHover?: (model: Model, env: SpreadsheetChildEnv) => void; + onStopHover?: (model: Model, env: SpreadsheetChildEnv) => void; } export interface ComputedAction @@ -105,7 +106,7 @@ export interface ComputedAction secondaryIcon: string; } -export type ActionBuilder = (env: SpreadsheetChildEnv) => ActionSpec[]; +export type ActionBuilder = (model: Model, env: SpreadsheetChildEnv) => ActionSpec[]; type ActionChildren = (ActionSpec | ActionBuilder)[]; export function createActions(menuItems: ActionSpec[]): Action[] { @@ -134,17 +135,17 @@ export function createAction(item: ActionSpec): Action { isEnabled: isEnabled, isActive: item.isActive, execute: item.execute - ? (env, isMiddleClick) => { - if (isEnabled(env)) { - return item.execute!(env, isMiddleClick); + ? (model, env, isMiddleClick) => { + if (isEnabled(model, env)) { + return item.execute!(model, env, isMiddleClick); } return undefined; } : undefined, children: children - ? (env) => { + ? (model, env) => { return children - .map((child) => (typeof child === "function" ? child(env) : child)) + .map((child) => (typeof child === "function" ? child(model, env) : child)) .flat() .map(createAction) .sort((a, b) => a.sequence - b.sequence); @@ -166,13 +167,17 @@ export function createAction(item: ActionSpec): Action { } export function getMenuItemsAndSeparators( + model: Model, env: SpreadsheetChildEnv, actions: Action[] ): MenuItemOrSeparator[] { const menuItemsAndSeparators: MenuItemOrSeparator[] = []; for (let i = 0; i < actions.length; i++) { const menuItem = actions[i]; - if (menuItem.isVisible(env) && (!isRootMenu(menuItem) || hasVisibleChildren(env, menuItem))) { + if ( + menuItem.isVisible(model, env) && + (!isRootMenu(menuItem) || hasVisibleChildren(model, env, menuItem)) + ) { menuItemsAndSeparators.push(menuItem); } if ( @@ -196,17 +201,17 @@ export function isRootMenu(menu: Action) { return !menu.execute; } -export function hasVisibleChildren(env: SpreadsheetChildEnv, menu: Action) { - return menu.children(env).some((child) => child.isVisible(env)); +export function hasVisibleChildren(model: Model, env: SpreadsheetChildEnv, menu: Action) { + return menu.children(model, env).some((child) => child.isVisible(model, env)); } -export function isMenuItemEnabled(env: SpreadsheetChildEnv, menu: Action): boolean { - const children = menu.children?.(env); +export function isMenuItemEnabled(model: Model, env: SpreadsheetChildEnv, menu: Action): boolean { + const children = menu.children?.(model, env); if (children.length) { - return children.some((child) => isMenuItemEnabled(env, child)); + return children.some((child) => isMenuItemEnabled(model, env, child)); } else { - if (menu.isEnabled(env)) { - return env.model.getters.isReadonly() ? menu.isReadonlyAllowed : true; + if (menu.isEnabled(model, env)) { + return model.getters.isReadonly() ? menu.isReadonlyAllowed : true; } return false; } diff --git a/src/actions/data_actions.ts b/src/actions/data_actions.ts index f143e52a4d..f8aad08770 100644 --- a/src/actions/data_actions.ts +++ b/src/actions/data_actions.ts @@ -12,10 +12,10 @@ export const sortRange: ActionSpec = { export const sortAscending: ActionSpec = { name: _t("Ascending (A ⟶ Z)"), - execute: (env) => { - const { anchor, zones } = env.model.getters.getSelection(); - const sheetId = env.model.getters.getActiveSheetId(); - interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "asc"); + execute: (model, env) => { + const { anchor, zones } = model.getters.getSelection(); + const sheetId = model.getters.getActiveSheetId(); + interactiveSortSelection(model, env, sheetId, anchor.cell, zones[0], "asc"); }, icon: "o-spreadsheet-Icon.SORT_ASCENDING", }; @@ -27,28 +27,28 @@ export const dataCleanup: ActionSpec = { export const removeDuplicates: ActionSpec = { name: _t("Remove duplicates"), - execute: (env) => { - if (getZoneArea(env.model.getters.getSelectedZone()) === 1) { - env.model.selection.selectTableAroundSelection(); + execute: (model, env) => { + if (getZoneArea(model.getters.getSelectedZone()) === 1) { + model.selection.selectTableAroundSelection(); } env.openSidePanel("RemoveDuplicates", {}); }, - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, }; export const trimWhitespace: ActionSpec = { name: _t("Trim whitespace"), - execute: (env) => { - env.model.dispatch("TRIM_WHITESPACE"); + execute: (model) => { + model.dispatch("TRIM_WHITESPACE"); }, }; export const sortDescending: ActionSpec = { name: _t("Descending (Z ⟶ A)"), - execute: (env) => { - const { anchor, zones } = env.model.getters.getSelection(); - const sheetId = env.model.getters.getActiveSheetId(); - interactiveSortSelection(env, sheetId, anchor.cell, zones[0], "desc"); + execute: (model, env) => { + const { anchor, zones } = model.getters.getSelection(); + const sheetId = model.getters.getActiveSheetId(); + interactiveSortSelection(model, env, sheetId, anchor.cell, zones[0], "desc"); }, icon: "o-spreadsheet-Icon.SORT_DESCENDING", }; @@ -65,14 +65,14 @@ export const createRemoveFilterTool: ActionSpec = { export const splitToColumns: ActionSpec = { name: _t("Split text to columns"), sequence: 1, - execute: (env) => env.openSidePanel("SplitToColumns", {}), - isEnabled: (env) => !env.isSmall && env.model.getters.isSingleColSelected(), + execute: (model, env) => env.openSidePanel("SplitToColumns", {}), + isEnabled: (model, env) => !env.isSmall && model.getters.isSingleColSelected(), icon: "o-spreadsheet-Icon.SPLIT_TEXT", }; export const columnStatistics: ActionSpec = { name: _t("Column statistics"), - execute: (env) => env.openSidePanel("ColumnStats", {}), + execute: (model, env) => env.openSidePanel("ColumnStats", {}), icon: "o-spreadsheet-Icon.COLUMN_STATS", }; @@ -82,8 +82,8 @@ export const reinsertDynamicPivotMenu: ActionSpec = { sequence: 60, icon: "o-spreadsheet-Icon.INSERT_PIVOT", children: [ACTIONS.REINSERT_DYNAMIC_PIVOT_CHILDREN], - isVisible: (env) => - env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()), + isVisible: (model) => + model.getters.getPivotIds().some((id) => model.getters.getPivot(id).isValid()), }; export const reinsertStaticPivotMenu: ActionSpec = { @@ -92,6 +92,6 @@ export const reinsertStaticPivotMenu: ActionSpec = { sequence: 70, icon: "o-spreadsheet-Icon.INSERT_PIVOT", children: [ACTIONS.REINSERT_STATIC_PIVOT_CHILDREN], - isVisible: (env) => - env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()), + isVisible: (model) => + model.getters.getPivotIds().some((id) => model.getters.getPivot(id).isValid()), }; diff --git a/src/actions/edit_actions.ts b/src/actions/edit_actions.ts index 6a3c2f376e..5611c65b27 100644 --- a/src/actions/edit_actions.ts +++ b/src/actions/edit_actions.ts @@ -2,6 +2,7 @@ import { interactiveCut } from "../helpers/ui/cut_interactive"; import { interactiveAddMerge } from "../helpers/ui/merge_interactive"; import { handlePasteResult } from "../helpers/ui/paste_interactive"; import { doesAnyZoneCrossFrozenPane, getZoneArea, hasOverlappingZones } from "../helpers/zones"; +import { Model } from "../model"; import { _t } from "../translation"; import { SpreadsheetChildEnv } from "../types/spreadsheet_env"; import { ActionSpec } from "./action"; @@ -10,8 +11,8 @@ import * as ACTIONS from "./menu_items_actions"; export const undo: ActionSpec = { name: _t("Undo"), shortcut: "Ctrl+Z", - execute: (env) => env.model.dispatch("REQUEST_UNDO"), - isEnabled: (env) => env.model.getters.canUndo(), + execute: (model) => model.dispatch("REQUEST_UNDO"), + isEnabled: (model) => model.getters.canUndo(), isEnabledOnLockedSheet: true, icon: "o-spreadsheet-Icon.UNDO", }; @@ -19,8 +20,8 @@ export const undo: ActionSpec = { export const redo: ActionSpec = { name: _t("Redo"), shortcut: "Ctrl+Y", - execute: (env) => env.model.dispatch("REQUEST_REDO"), - isEnabled: (env) => env.model.getters.canRedo(), + execute: (model) => model.dispatch("REQUEST_REDO"), + isEnabled: (model) => model.getters.canRedo(), isEnabledOnLockedSheet: true, icon: "o-spreadsheet-Icon.REDO", }; @@ -29,9 +30,9 @@ export const copy: ActionSpec = { name: _t("Copy"), shortcut: "Ctrl+C", isReadonlyAllowed: true, - execute: async (env) => { - env.model.dispatch("COPY"); - await env.clipboard.write(await env.model.getters.getClipboardTextAndImageContent()); + execute: async (model, env) => { + model.dispatch("COPY"); + await env.clipboard.write(await model.getters.getClipboardTextAndImageContent()); }, isEnabledOnLockedSheet: true, icon: "o-spreadsheet-Icon.CLIPBOARD", @@ -40,9 +41,9 @@ export const copy: ActionSpec = { export const cut: ActionSpec = { name: _t("Cut"), shortcut: "Ctrl+X", - execute: async (env) => { - interactiveCut(env); - await env.clipboard.write(await env.model.getters.getClipboardTextAndImageContent()); + execute: async (model, env) => { + interactiveCut(model, env); + await env.clipboard.write(await model.getters.getClipboardTextAndImageContent()); }, icon: "o-spreadsheet-Icon.CUT", }; @@ -56,8 +57,8 @@ export const paste: ActionSpec = { export const pasteSpecial: ActionSpec = { name: _t("Paste special"), - isVisible: (env): boolean => { - return !env.model.getters.isCutOperation(); + isVisible: (model): boolean => { + return !model.getters.isCutOperation(); }, icon: "o-spreadsheet-Icon.PASTE", }; @@ -78,26 +79,26 @@ export const findAndReplace: ActionSpec = { shortcut: "Ctrl+H", isReadonlyAllowed: true, isEnabledOnLockedSheet: true, - execute: (env) => { + execute: (model, env) => { env.openSidePanel("FindAndReplace", {}); }, - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, icon: "o-spreadsheet-Icon.SEARCH", }; export const deleteValues: ActionSpec = { name: _t("Delete values"), - execute: (env) => - env.model.dispatch("DELETE_UNFILTERED_CONTENT", { - sheetId: env.model.getters.getActiveSheetId(), - target: env.model.getters.getSelectedZones(), + execute: (model, env) => + model.dispatch("DELETE_UNFILTERED_CONTENT", { + sheetId: model.getters.getActiveSheetId(), + target: model.getters.getSelectedZones(), }), }; export const deleteRows: ActionSpec = { name: ACTIONS.REMOVE_ROWS_NAME, execute: ACTIONS.REMOVE_ROWS_ACTION, - isVisible: (env: SpreadsheetChildEnv) => ACTIONS.CAN_REMOVE_COLUMNS_ROWS("ROW", env), + isVisible: (model) => ACTIONS.CAN_REMOVE_COLUMNS_ROWS(model, "ROW"), }; export const deleteRow: ActionSpec = { @@ -113,7 +114,7 @@ export const clearRows: ActionSpec = { export const deleteCols: ActionSpec = { name: ACTIONS.REMOVE_COLUMNS_NAME, execute: ACTIONS.REMOVE_COLUMNS_ACTION, - isVisible: (env: SpreadsheetChildEnv) => ACTIONS.CAN_REMOVE_COLUMNS_ROWS("COL", env), + isVisible: (model) => ACTIONS.CAN_REMOVE_COLUMNS_ROWS(model, "COL"), }; export const deleteCol: ActionSpec = { @@ -133,33 +134,33 @@ export const deleteCells: ActionSpec = { export const deleteCellShiftUp: ActionSpec = { name: _t("Delete cell and shift up"), - execute: (env) => { - const zone = env.model.getters.getSelectedZone(); - const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "ROW" }); - handlePasteResult(env, result); + execute: (model, env) => { + const zone = model.getters.getSelectedZone(); + const result = model.dispatch("DELETE_CELL", { zone, shiftDimension: "ROW" }); + handlePasteResult(model, env, result); }, }; export const deleteCellShiftLeft: ActionSpec = { name: _t("Delete cell and shift left"), - execute: (env) => { - const zone = env.model.getters.getSelectedZone(); - const result = env.model.dispatch("DELETE_CELL", { zone, shiftDimension: "COL" }); - handlePasteResult(env, result); + execute: (model, env) => { + const zone = model.getters.getSelectedZone(); + const result = model.dispatch("DELETE_CELL", { zone, shiftDimension: "COL" }); + handlePasteResult(model, env, result); }, }; export const mergeCells: ActionSpec = { name: _t("Merge cells"), - isEnabled: (env) => !cannotMerge(env), - isActive: (env) => hasMergeInAnySelectedZone(env), - execute: (env) => toggleMerge(env), + isEnabled: (model) => !cannotMerge(model), + isActive: (model) => hasMergeInAnySelectedZone(model), + execute: (model, env) => toggleMerge(model, env), icon: "o-spreadsheet-Icon.MERGE_CELL", }; export const editTable: ActionSpec = { name: () => _t("Edit table"), - execute: (env) => env.openSidePanel("TableSidePanel", {}), + execute: (model, env) => env.openSidePanel("TableSidePanel", {}), icon: "o-spreadsheet-Icon.EDIT_TABLE", }; @@ -169,10 +170,10 @@ export const deleteTable: ActionSpec = { icon: "o-spreadsheet-Icon.DELETE_TABLE", }; -function cannotMerge(env: SpreadsheetChildEnv): boolean { - const zones = env.model.getters.getSelectedZones(); - const { sheetId } = env.model.getters.getActivePosition(); - const { xSplit, ySplit } = env.model.getters.getPaneDivisions(sheetId); +function cannotMerge(model: Model): boolean { + const zones = model.getters.getSelectedZones(); + const { sheetId } = model.getters.getActivePosition(); + const { xSplit, ySplit } = model.getters.getPaneDivisions(sheetId); return ( zones.every((zone) => getZoneArea(zone) === 1) || doesAnyZoneCrossFrozenPane(zones, xSplit, ySplit) || @@ -180,31 +181,29 @@ function cannotMerge(env: SpreadsheetChildEnv): boolean { ); } -function hasMergeInAnySelectedZone(env: SpreadsheetChildEnv): boolean { - if (cannotMerge(env)) { +function hasMergeInAnySelectedZone(model: Model): boolean { + if (cannotMerge(model)) { return false; } - const sheetId = env.model.getters.getActiveSheetId(); - const zones = env.model.getters.getSelectedZones(); + const sheetId = model.getters.getActiveSheetId(); + const zones = model.getters.getSelectedZones(); return zones.some((zone) => { - return env.model.getters.getMergesInZone(sheetId, zone).length > 0; + return model.getters.getMergesInZone(sheetId, zone).length > 0; }); } -function toggleMerge(env: SpreadsheetChildEnv) { - if (cannotMerge(env)) { +function toggleMerge(model: Model, env: SpreadsheetChildEnv) { + if (cannotMerge(model)) { return; } - const target = env.model.getters.getSelectedZones(); - const sheetId = env.model.getters.getActiveSheetId(); - if (hasMergeInAnySelectedZone(env)) { - const mergesToRemove = target.flatMap((zone) => - env.model.getters.getMergesInZone(sheetId, zone) - ); - env.model.dispatch("REMOVE_MERGE", { sheetId, target: mergesToRemove }); + const target = model.getters.getSelectedZones(); + const sheetId = model.getters.getActiveSheetId(); + if (hasMergeInAnySelectedZone(model)) { + const mergesToRemove = target.flatMap((zone) => model.getters.getMergesInZone(sheetId, zone)); + model.dispatch("REMOVE_MERGE", { sheetId, target: mergesToRemove }); } else { - interactiveAddMerge(env, sheetId, target); + interactiveAddMerge(model, env, sheetId, target); } } diff --git a/src/actions/figure_menu_actions.ts b/src/actions/figure_menu_actions.ts index 9b9cd451c0..ebff0ea794 100644 --- a/src/actions/figure_menu_actions.ts +++ b/src/actions/figure_menu_actions.ts @@ -1,64 +1,63 @@ -import { UID } from ".."; +import { Model, UID } from ".."; import { downloadFile } from "../components/helpers/dom_helpers"; import { chartToImageFile, chartToImageUrl } from "../helpers/figures/charts/chart_ui_common"; import { getMaxFigureSize } from "../helpers/figures/figure/figure"; import { deepEquals } from "../helpers/misc"; import { _t } from "../translation"; -import { SpreadsheetChildEnv } from "../types/spreadsheet_env"; import { Action, ActionSpec, createActions } from "./action"; -export function getChartMenuActions(figureId: UID, env: SpreadsheetChildEnv): Action[] { - const chartId = env.model.getters.getChartIdFromFigureId(figureId); +export function getChartMenuActions(figureId: UID, model: Model): Action[] { + const chartId = model.getters.getChartIdFromFigureId(figureId); if (!chartId) { return []; } const menuItemSpecs: ActionSpec[] = [ - getMergeCarouselMenuItem(figureId, env), + getMergeCarouselMenuItem(figureId), { id: "edit", name: _t("Edit"), - execute: () => { - env.model.dispatch("SELECT_FIGURE", { figureId }); + execute: (model, env) => { + model.dispatch("SELECT_FIGURE", { figureId }); env.openSidePanel("ChartPanel"); }, icon: "o-spreadsheet-Icon.EDIT", - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, }, - getCopyMenuItem(figureId, env), - getCutMenuItem(figureId, env), - getCopyAsImageMenuItem(figureId, env), - getDownloadChartMenuItem(figureId, env), - getDeleteMenuItem(figureId, env), + getCopyMenuItem(figureId), + getCutMenuItem(figureId), + getCopyAsImageMenuItem(figureId), + getDownloadChartMenuItem(figureId), + getDeleteMenuItem(figureId), ]; return createActions(menuItemSpecs).filter((action) => - env.model.getters.isReadonly() ? action.isReadonlyAllowed : true + model.getters.isReadonly() ? action.isReadonlyAllowed : true ); } -export function getImageMenuActions(figureId: UID, env: SpreadsheetChildEnv): Action[] { +export function getImageMenuActions(figureId: UID): Action[] { const menuItemSpecs: ActionSpec[] = [ - getCopyMenuItem(figureId, env, _t("Image copied to clipboard")), - getCutMenuItem(figureId, env), + getCopyMenuItem(figureId, _t("Image copied to clipboard")), + getCutMenuItem(figureId), { id: "reset_size", name: _t("Reset size"), - execute: async () => { - const sheetId = env.model.getters.getActiveSheetId(); - const figure = env.model.getters.getFigure(sheetId, figureId); + execute: async (model, env) => { + const sheetId = model.getters.getActiveSheetId(); + const figure = model.getters.getFigure(sheetId, figureId); if (!figure) { return; } - const imagePath = env.model.getters.getImagePath(figureId); + const imagePath = model.getters.getImagePath(figureId); const size = - env.model.getters.getImageSize(figureId) ?? + model.getters.getImageSize(figureId) ?? (await env.imageProvider?.getImageOriginalSize(imagePath)); - if (!env.model.getters.getImageSize(figureId)) { - const image = env.model.getters.getImage(figureId); + if (!model.getters.getImageSize(figureId)) { + const image = model.getters.getImage(figureId); image.size = size; } const { col, row } = figure; - const { height, width } = getMaxFigureSize(env.model.getters, size); - env.model.dispatch("UPDATE_FIGURE", { + const { height, width } = getMaxFigureSize(model.getters, size); + model.dispatch("UPDATE_FIGURE", { sheetId, figureId, height, @@ -72,39 +71,39 @@ export function getImageMenuActions(figureId: UID, env: SpreadsheetChildEnv): Ac { id: "download", name: _t("Download"), - execute: async () => { - env.model.dispatch("SELECT_FIGURE", { figureId }); - const path = env.model.getters.getImagePath(figureId); + execute: async (model) => { + model.dispatch("SELECT_FIGURE", { figureId }); + const path = model.getters.getImagePath(figureId); downloadFile(path, "image"); }, icon: "o-spreadsheet-Icon.DOWNLOAD", }, - getDeleteMenuItem(figureId, env), + getDeleteMenuItem(figureId), ]; return createActions(menuItemSpecs); } -export function getCarouselMenuActions(figureId: UID, env: SpreadsheetChildEnv): Action[] { - const isChartSelected = (env: SpreadsheetChildEnv) => - env.model.getters.getSelectedCarouselItem(figureId)?.type === "chart"; +export function getCarouselMenuActions(figureId: UID, model: Model): Action[] { + const isChartSelected = (model: Model) => + model.getters.getSelectedCarouselItem(figureId)?.type === "chart"; const menuItemSpecs: ActionSpec[] = [ { id: "edit_carousel", name: _t("Edit carousel"), - execute: () => { - env.model.dispatch("SELECT_FIGURE", { figureId }); + execute: (model, env) => { + model.dispatch("SELECT_FIGURE", { figureId }); env.openSidePanel("CarouselPanel", { figureId }); }, icon: "o-spreadsheet-Icon.EDIT", - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, }, { - ...getCopyMenuItem(figureId, env, _t("Carousel copied to clipboard")), + ...getCopyMenuItem(figureId, _t("Carousel copied to clipboard")), name: _t("Copy carousel"), }, - { ...getCutMenuItem(figureId, env), name: _t("Cut carousel") }, + { ...getCutMenuItem(figureId), name: _t("Cut carousel") }, { - ...getDeleteMenuItem(figureId, env), + ...getDeleteMenuItem(figureId), name: _t("Delete carousel"), separator: true, }, @@ -112,21 +111,21 @@ export function getCarouselMenuActions(figureId: UID, env: SpreadsheetChildEnv): { id: "edit_chart", name: _t("Edit chart"), - execute: () => { - env.model.dispatch("SELECT_FIGURE", { figureId }); + execute: (model, env) => { + model.dispatch("SELECT_FIGURE", { figureId }); env.openSidePanel("ChartPanel", {}); }, icon: "o-spreadsheet-Icon.EDIT", - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, isVisible: isChartSelected, }, { - ...getCopyAsImageMenuItem(figureId, env), + ...getCopyAsImageMenuItem(figureId), isVisible: isChartSelected, name: _t("Copy chart as image"), }, { - ...getDownloadChartMenuItem(figureId, env), + ...getDownloadChartMenuItem(figureId), isVisible: isChartSelected, name: _t("Download chart"), }, @@ -134,62 +133,58 @@ export function getCarouselMenuActions(figureId: UID, env: SpreadsheetChildEnv): id: "popout_chart", name: _t("Pop out chart"), icon: "o-spreadsheet-Icon.EXTERNAL", - execute: () => { - const selectedItem = env.model.getters.getSelectedCarouselItem(figureId); + execute: (model) => { + const selectedItem = model.getters.getSelectedCarouselItem(figureId); if (!selectedItem || selectedItem.type !== "chart") { return; } - env.model.dispatch("POPOUT_CHART_FROM_CAROUSEL", { + model.dispatch("POPOUT_CHART_FROM_CAROUSEL", { carouselId: figureId, chartId: selectedItem.chartId, - sheetId: env.model.getters.getActiveSheetId(), + sheetId: model.getters.getActiveSheetId(), }); }, isVisible: isChartSelected, }, { id: "delete_carousel_item", - name: (env) => { - const item = env.model.getters.getSelectedCarouselItem(figureId); + name: (model) => { + const item = model.getters.getSelectedCarouselItem(figureId); return item?.type === "chart" ? _t("Delete chart") : _t("Delete data view"); }, - execute: () => { - const item = env.model.getters.getSelectedCarouselItem(figureId); + execute: (model) => { + const item = model.getters.getSelectedCarouselItem(figureId); if (!item) { return; } - const carousel = env.model.getters.getCarousel(figureId); + const carousel = model.getters.getCarousel(figureId); const items = carousel.items.filter((itm) => !deepEquals(itm, item)); - env.model.dispatch("UPDATE_CAROUSEL", { + model.dispatch("UPDATE_CAROUSEL", { figureId, - sheetId: env.model.getters.getActiveSheetId(), + sheetId: model.getters.getActiveSheetId(), definition: { ...carousel, items }, }); }, icon: "o-spreadsheet-Icon.TRASH", - isVisible: (env) => env.model.getters.getCarousel(figureId).items.length >= 1, + isVisible: (model) => model.getters.getCarousel(figureId).items.length >= 1, }, ]; return createActions(menuItemSpecs).filter((action) => - env.model.getters.isReadonly() ? action.isReadonlyAllowed : true + model.getters.isReadonly() ? action.isReadonlyAllowed : true ); } -function getCopyMenuItem( - figureId: UID, - env: SpreadsheetChildEnv, - copiedNotificationMessage?: string -): ActionSpec { +function getCopyMenuItem(figureId: UID, copiedNotificationMessage?: string): ActionSpec { return { id: "copy", name: _t("Copy"), shortcut: "Ctrl+C", - execute: async () => { - if (!env.model.getters.getSelectedFigureIds().includes(figureId)) { - env.model.dispatch("SELECT_FIGURE", { figureId }); + execute: async (model, env) => { + if (!model.getters.getSelectedFigureIds().includes(figureId)) { + model.dispatch("SELECT_FIGURE", { figureId }); } - env.model.dispatch("COPY"); - const osClipboardContent = await env.model.getters.getClipboardTextAndImageContent(); + model.dispatch("COPY"); + const osClipboardContent = await model.getters.getClipboardTextAndImageContent(); await env.clipboard.write(osClipboardContent); if (copiedNotificationMessage) { env.notifyUser({ sticky: false, type: "success", text: copiedNotificationMessage }); @@ -200,36 +195,36 @@ function getCopyMenuItem( }; } -function getCutMenuItem(figureId: UID, env: SpreadsheetChildEnv): ActionSpec { +function getCutMenuItem(figureId: UID): ActionSpec { return { id: "cut", name: _t("Cut"), shortcut: "Ctrl+X", - execute: async () => { - if (!env.model.getters.getSelectedFigureIds().includes(figureId)) { - env.model.dispatch("SELECT_FIGURE", { figureId }); + execute: async (model, env) => { + if (!model.getters.getSelectedFigureIds().includes(figureId)) { + model.dispatch("SELECT_FIGURE", { figureId }); } - env.model.dispatch("CUT"); - await env.clipboard.write(await env.model.getters.getClipboardTextAndImageContent()); + model.dispatch("CUT"); + await env.clipboard.write(await model.getters.getClipboardTextAndImageContent()); }, icon: "o-spreadsheet-Icon.CUT", }; } -function getCopyAsImageMenuItem(figureId: UID, env: SpreadsheetChildEnv): ActionSpec { +function getCopyAsImageMenuItem(figureId: UID): ActionSpec { return { id: "copy_as_image", name: _t("Copy as image"), icon: "o-spreadsheet-Icon.COPY_AS_IMAGE", - execute: async () => { - const figureSheetId = env.model.getters.getFigureSheetId(figureId)!; - const figure = env.model.getters.getFigure(figureSheetId, figureId)!; - const chartId = env.model.getters.getChartIdFromFigureId(figureId); + execute: async (model, env) => { + const figureSheetId = model.getters.getFigureSheetId(figureId)!; + const figure = model.getters.getFigure(figureSheetId, figureId)!; + const chartId = model.getters.getChartIdFromFigureId(figureId); if (!chartId) { return; } - const chartType = env.model.getters.getChartType(chartId); - const runtime = env.model.getters.getChartRuntime(chartId); + const chartType = model.getters.getChartType(chartId); + const runtime = model.getters.getChartRuntime(chartId); const blob = await chartToImageFile(runtime, figure, chartType); if (!blob) { return; @@ -256,52 +251,52 @@ function getCopyAsImageMenuItem(figureId: UID, env: SpreadsheetChildEnv): Action }); env.notifyUser({ sticky: false, type: "success", text: _t("Chart copied to clipboard") }); }, - isVisible: (env) => env.model.getters.getSelectedFigureIds().length <= 1, + isVisible: (model) => model.getters.getSelectedFigureIds().length <= 1, isReadonlyAllowed: true, isEnabledOnLockedSheet: true, }; } -function getDownloadChartMenuItem(figureId: UID, env: SpreadsheetChildEnv): ActionSpec { +function getDownloadChartMenuItem(figureId: UID): ActionSpec { return { id: "download", name: _t("Download"), icon: "o-spreadsheet-Icon.DOWNLOAD", - execute: async () => { - const figureSheetId = env.model.getters.getFigureSheetId(figureId)!; - const figure = env.model.getters.getFigure(figureSheetId, figureId)!; - const chartId = env.model.getters.getChartIdFromFigureId(figureId); + execute: async (model, env) => { + const figureSheetId = model.getters.getFigureSheetId(figureId)!; + const figure = model.getters.getFigure(figureSheetId, figureId)!; + const chartId = model.getters.getChartIdFromFigureId(figureId); if (!chartId) { return; } - const chartType = env.model.getters.getChartType(chartId); - const runtime = env.model.getters.getChartRuntime(chartId); + const chartType = model.getters.getChartType(chartId); + const runtime = model.getters.getChartRuntime(chartId); const url = await chartToImageUrl(runtime, figure, chartType); if (!url) { return; } downloadFile(url, "chart"); }, - isVisible: (env) => env.model.getters.getSelectedFigureIds().length <= 1, + isVisible: (model) => model.getters.getSelectedFigureIds().length <= 1, isReadonlyAllowed: true, isEnabledOnLockedSheet: true, }; } -function getDeleteMenuItem(figureId: UID, env: SpreadsheetChildEnv): ActionSpec { +function getDeleteMenuItem(figureId: UID): ActionSpec { return { id: "delete", name: _t("Delete"), - execute: () => { - const selectedFiguresIds = env.model.getters.getSelectedFigureIds(); + execute: (model) => { + const selectedFiguresIds = model.getters.getSelectedFigureIds(); if (selectedFiguresIds.includes(figureId)) { - env.model.dispatch("DELETE_FIGURES", { - sheetId: env.model.getters.getActiveSheetId(), + model.dispatch("DELETE_FIGURES", { + sheetId: model.getters.getActiveSheetId(), figureIds: selectedFiguresIds, }); } else { - env.model.dispatch("DELETE_FIGURE", { - sheetId: env.model.getters.getActiveSheetId(), + model.dispatch("DELETE_FIGURE", { + sheetId: model.getters.getActiveSheetId(), figureId, }); } @@ -310,23 +305,23 @@ function getDeleteMenuItem(figureId: UID, env: SpreadsheetChildEnv): ActionSpec }; } -function getMergeCarouselMenuItem(figureId: UID, env: SpreadsheetChildEnv): ActionSpec { +function getMergeCarouselMenuItem(figureId: UID): ActionSpec { return { id: "mergeCarousel", name: _t("Create carousel"), - isVisible: (env) => { - const selectedFiguresIds = env.model.getters.getSelectedFigureIds(); + isVisible: (model) => { + const selectedFiguresIds = model.getters.getSelectedFigureIds(); if (selectedFiguresIds.length < 2 || !selectedFiguresIds.includes(figureId)) { return false; } - const sheetId = env.model.getters.getActiveSheetId(); - const figures = selectedFiguresIds.map((id) => env.model.getters.getFigure(sheetId, id)); + const sheetId = model.getters.getActiveSheetId(); + const figures = selectedFiguresIds.map((id) => model.getters.getFigure(sheetId, id)); return !figures.some((f) => f === undefined || f.tag !== "chart"); }, - execute: () => { - const sheetId = env.model.getters.getActiveSheetId(); - const chartFigureIds = env.model.getters.getSelectedFigureIds(); - env.model.dispatch("MERGE_CHART_FIGURES_INTO_CAROUSEL", { + execute: (model) => { + const sheetId = model.getters.getActiveSheetId(); + const chartFigureIds = model.getters.getSelectedFigureIds(); + model.dispatch("MERGE_CHART_FIGURES_INTO_CAROUSEL", { sheetId, baseFigureId: figureId, chartFigureIds, diff --git a/src/actions/format_actions.ts b/src/actions/format_actions.ts index b5968c8e5a..36a1659b2b 100644 --- a/src/actions/format_actions.ts +++ b/src/actions/format_actions.ts @@ -14,23 +14,23 @@ import { roundFormat, } from "../helpers/format/format"; import { getDateTimeFormat } from "../helpers/locale"; +import { Model } from "../model"; import { _t } from "../translation"; import { CellValue } from "../types/cells"; import { Format } from "../types/format"; import { DEFAULT_LOCALE } from "../types/locale"; import { Align, VerticalAlign, Wrapping } from "../types/misc"; -import { SpreadsheetChildEnv } from "../types/spreadsheet_env"; import { ActionSpec } from "./action"; import * as ACTIONS from "./menu_items_actions"; import { setFormatter, setStyle } from "./menu_items_actions"; export interface NumberFormatActionSpec extends ActionSpec { - format?: Format | ((env: SpreadsheetChildEnv) => Format); + format?: Format | ((model: Model) => Format); } /** * Create a format action specification for a given format. - * The format can be dynamically computed from the environment. + * The format can be dynamically computed from the model. */ export function createFormatActionSpec({ name, @@ -39,32 +39,32 @@ export function createFormatActionSpec({ }: { name: string; descriptionValue: CellValue; - format: Format | ((env: SpreadsheetChildEnv) => Format); + format: Format | ((model: Model) => Format); }): NumberFormatActionSpec { const formatCallback = typeof format === "function" ? format : () => format; return { name, - description: (env) => + description: (model) => formatValue(descriptionValue, { - format: formatCallback(env), - locale: env.model.getters.getLocale(), + format: formatCallback(model), + locale: model.getters.getLocale(), }), - execute: (env) => setFormatter(env, formatCallback(env)), - isActive: (env) => isFormatSelected(env, formatCallback(env)), + execute: (model) => setFormatter(model, formatCallback(model)), + isActive: (model) => isFormatSelected(model, formatCallback(model)), format, }; } export const formatNumberAutomatic: NumberFormatActionSpec = { name: _t("Automatic"), - execute: (env) => setFormatter(env, ""), - isActive: (env) => isAutomaticFormatSelected(env), + execute: (model) => setFormatter(model, ""), + isActive: (model) => isAutomaticFormatSelected(model), }; export const formatNumberPlainText: NumberFormatActionSpec = { name: _t("Plain text"), - execute: (env) => setFormatter(env, "@"), - isActive: (env) => isFormatSelected(env, "@"), + execute: (model) => setFormatter(model, "@"), + isActive: (model) => isFormatSelected(model, "@"), }; export const formatNumberNumber = createFormatActionSpec({ @@ -94,20 +94,18 @@ export const formatNumberScientific = createFormatActionSpec({ export const formatNumberCurrency = createFormatActionSpec({ name: _t("Currency"), descriptionValue: 1000.12, - format: (env) => createCurrencyFormat(env.model.config.defaultCurrency || DEFAULT_CURRENCY), + format: (model) => createCurrencyFormat(model.config.defaultCurrency || DEFAULT_CURRENCY), }); export const formatNumberCurrencyRounded: NumberFormatActionSpec = { ...createFormatActionSpec({ name: _t("Currency rounded"), descriptionValue: 1000, - format: (env) => - roundFormat(createCurrencyFormat(env.model.config.defaultCurrency || DEFAULT_CURRENCY)), + format: (model) => + roundFormat(createCurrencyFormat(model.config.defaultCurrency || DEFAULT_CURRENCY)), }), - isVisible: (env) => { - const currencyFormat = createCurrencyFormat( - env.model.config.defaultCurrency || DEFAULT_CURRENCY - ); + isVisible: (model) => { + const currencyFormat = createCurrencyFormat(model.config.defaultCurrency || DEFAULT_CURRENCY); const roundedFormat = roundFormat(currencyFormat); return currencyFormat !== roundedFormat; }, @@ -116,34 +114,34 @@ export const formatNumberCurrencyRounded: NumberFormatActionSpec = { export const formatNumberAccounting = createFormatActionSpec({ name: _t("Accounting"), descriptionValue: -1000.12, - format: (env) => createAccountingFormat(env.model.config.defaultCurrency || DEFAULT_CURRENCY), + format: (model) => createAccountingFormat(model.config.defaultCurrency || DEFAULT_CURRENCY), }); export const EXAMPLE_DATE = parseLiteral("2023/09/26 10:43:00 PM", DEFAULT_LOCALE); export const formatCustomCurrency: ActionSpec = { name: _t("Custom currency"), - isVisible: (env) => env.loadCurrencies !== undefined && !env.isSmall, - execute: (env) => env.openSidePanel("MoreFormats", { category: "currency" }), + isVisible: (model, env) => env.loadCurrencies !== undefined && !env.isSmall, + execute: (model, env) => env.openSidePanel("MoreFormats", { category: "currency" }), }; export const formatNumberDate = createFormatActionSpec({ name: _t("Date"), descriptionValue: EXAMPLE_DATE, - format: (env) => env.model.getters.getLocale().dateFormat, + format: (model) => model.getters.getLocale().dateFormat, }); export const formatNumberTime = createFormatActionSpec({ name: _t("Time"), descriptionValue: EXAMPLE_DATE, - format: (env) => env.model.getters.getLocale().timeFormat, + format: (model) => model.getters.getLocale().timeFormat, }); export const formatNumberDateTime = createFormatActionSpec({ name: _t("Date time"), descriptionValue: EXAMPLE_DATE, - format: (env) => { - const locale = env.model.getters.getLocale(); + format: (model) => { + const locale = model.getters.getLocale(); return getDateTimeFormat(locale); }, }); @@ -156,14 +154,14 @@ export const formatNumberDuration = createFormatActionSpec({ export const customDateFormat: ActionSpec = { name: _t("Custom date and time"), - isVisible: (env) => !env.isSmall, - execute: (env) => env.openSidePanel("MoreFormats", { category: "date" }), + isVisible: (model, env) => !env.isSmall, + execute: (model, env) => env.openSidePanel("MoreFormats", { category: "date" }), }; export const customNumberFormat: ActionSpec = { name: _t("Custom number format"), - isVisible: (env) => !env.isSmall, - execute: (env) => env.openSidePanel("MoreFormats", { category: "number" }), + isVisible: (model, env) => !env.isSmall, + execute: (model, env) => env.openSidePanel("MoreFormats", { category: "number" }), }; export const formatNumberFullDateTime = createFormatActionSpec({ @@ -175,10 +173,10 @@ export const formatNumberFullDateTime = createFormatActionSpec({ export const increaseDecimalPlaces: ActionSpec = { name: _t("Increase decimal places"), icon: "o-spreadsheet-Icon.INCREASE_DECIMAL", - execute: (env) => - env.model.dispatch("SET_DECIMAL", { - sheetId: env.model.getters.getActiveSheetId(), - target: env.model.getters.getSelectedZones(), + execute: (model) => + model.dispatch("SET_DECIMAL", { + sheetId: model.getters.getActiveSheetId(), + target: model.getters.getSelectedZones(), step: 1, }), }; @@ -186,10 +184,10 @@ export const increaseDecimalPlaces: ActionSpec = { export const decreaseDecimalPlaces: ActionSpec = { name: _t("Decrease decimal places"), icon: "o-spreadsheet-Icon.DECRASE_DECIMAL", - execute: (env) => - env.model.dispatch("SET_DECIMAL", { - sheetId: env.model.getters.getActiveSheetId(), - target: env.model.getters.getSelectedZones(), + execute: (model) => + model.dispatch("SET_DECIMAL", { + sheetId: model.getters.getActiveSheetId(), + target: model.getters.getSelectedZones(), step: -1, }), }; @@ -197,39 +195,39 @@ export const decreaseDecimalPlaces: ActionSpec = { export const formatBold: ActionSpec = { name: _t("Bold"), shortcut: "Ctrl+B", - execute: (env) => setStyle(env, { bold: !env.model.getters.getCurrentStyle().bold }), + execute: (model) => setStyle(model, { bold: !model.getters.getCurrentStyle().bold }), icon: "o-spreadsheet-Icon.BOLD", - isActive: (env) => !!env.model.getters.getCurrentStyle().bold, + isActive: (model) => !!model.getters.getCurrentStyle().bold, }; export const formatItalic: ActionSpec = { name: _t("Italic"), shortcut: "Ctrl+I", - execute: (env) => setStyle(env, { italic: !env.model.getters.getCurrentStyle().italic }), + execute: (model) => setStyle(model, { italic: !model.getters.getCurrentStyle().italic }), icon: "o-spreadsheet-Icon.ITALIC", - isActive: (env) => !!env.model.getters.getCurrentStyle().italic, + isActive: (model) => !!model.getters.getCurrentStyle().italic, }; export const formatUnderline: ActionSpec = { name: _t("Underline"), shortcut: "Ctrl+U", - execute: (env) => setStyle(env, { underline: !env.model.getters.getCurrentStyle().underline }), + execute: (model) => setStyle(model, { underline: !model.getters.getCurrentStyle().underline }), icon: "o-spreadsheet-Icon.UNDERLINE", - isActive: (env) => !!env.model.getters.getCurrentStyle().underline, + isActive: (model) => !!model.getters.getCurrentStyle().underline, }; export const formatRotation: ActionSpec = { name: _t("Rotation"), - icon: (env) => getRotationIcon(env), + icon: (model) => getRotationIcon(model), }; -function setRotation(env: SpreadsheetChildEnv, rotation: number) { +function setRotation(model: Model, rotation: number) { rotation = Math.trunc(rotation / ROTATION_EPSILON) * ROTATION_EPSILON; - setStyle(env, { rotation }); + setStyle(model, { rotation }); } -function currentRotationEqual(env: SpreadsheetChildEnv, rotation: number): boolean { - const current = env.model.getters.getCurrentStyle().rotation; +function currentRotationEqual(model: Model, rotation: number): boolean { + const current = model.getters.getCurrentStyle().rotation; if (current === undefined) { return rotation === 0; } @@ -238,45 +236,45 @@ function currentRotationEqual(env: SpreadsheetChildEnv, rotation: number): boole export const formatNoRotation: ActionSpec = { name: _t("No rotation"), - execute: (env) => setStyle(env, { rotation: 0 }), + execute: (model) => setStyle(model, { rotation: 0 }), icon: "o-spreadsheet-Icon.ROTATION-0", - isActive: (env) => currentRotationEqual(env, 0), + isActive: (model) => currentRotationEqual(model, 0), }; export const formatRotation45: ActionSpec = { name: _t("45° rotation"), - execute: (env) => setRotation(env, Math.PI / 4), + execute: (model) => setRotation(model, Math.PI / 4), icon: "o-spreadsheet-Icon.ROTATION-45", - isActive: (env) => currentRotationEqual(env, Math.PI / 4), + isActive: (model) => currentRotationEqual(model, Math.PI / 4), }; export const formatRotation90: ActionSpec = { name: _t("90° rotation"), - execute: (env) => setRotation(env, Math.PI / 2), + execute: (model) => setRotation(model, Math.PI / 2), icon: "o-spreadsheet-Icon.ROTATION-90", - isActive: (env) => currentRotationEqual(env, Math.PI / 2), + isActive: (model) => currentRotationEqual(model, Math.PI / 2), }; export const formatRotation270: ActionSpec = { name: _t("-90° rotation"), - execute: (env) => setRotation(env, -Math.PI / 2), + execute: (model) => setRotation(model, -Math.PI / 2), icon: "o-spreadsheet-Icon.ROTATION-270", - isActive: (env) => currentRotationEqual(env, -Math.PI / 2), + isActive: (model) => currentRotationEqual(model, -Math.PI / 2), }; export const formatRotation315: ActionSpec = { name: _t("-45° rotation"), - execute: (env) => setRotation(env, -Math.PI / 4), + execute: (model) => setRotation(model, -Math.PI / 4), icon: "o-spreadsheet-Icon.ROTATION-315", - isActive: (env) => currentRotationEqual(env, -Math.PI / 4), + isActive: (model) => currentRotationEqual(model, -Math.PI / 4), }; export const formatStrikethrough: ActionSpec = { name: _t("Strikethrough"), - execute: (env) => - setStyle(env, { strikethrough: !env.model.getters.getCurrentStyle().strikethrough }), + execute: (model) => + setStyle(model, { strikethrough: !model.getters.getCurrentStyle().strikethrough }), icon: "o-spreadsheet-Icon.STRIKE", - isActive: (env) => !!env.model.getters.getCurrentStyle().strikethrough, + isActive: (model) => !!model.getters.getCurrentStyle().strikethrough, }; export const formatFontSize: ActionSpec = { @@ -292,56 +290,56 @@ export const formatAlignment: ActionSpec = { export const formatAlignmentHorizontal: ActionSpec = { name: _t("Horizontal align"), - icon: (env) => getHorizontalAlignmentIcon(env), + icon: (model) => getHorizontalAlignmentIcon(model), }; export const formatAlignmentLeft: ActionSpec = { name: _t("Left"), shortcut: "Ctrl+Shift+L", - execute: (env) => ACTIONS.setStyle(env, { align: "left" }), - isActive: (env) => getHorizontalAlign(env) === "left", + execute: (model) => ACTIONS.setStyle(model, { align: "left" }), + isActive: (model) => getHorizontalAlign(model) === "left", icon: "o-spreadsheet-Icon.ALIGN_LEFT", }; export const formatAlignmentCenter: ActionSpec = { name: _t("Center"), shortcut: "Ctrl+Shift+E", - execute: (env) => ACTIONS.setStyle(env, { align: "center" }), - isActive: (env) => getHorizontalAlign(env) === "center", + execute: (model) => ACTIONS.setStyle(model, { align: "center" }), + isActive: (model) => getHorizontalAlign(model) === "center", icon: "o-spreadsheet-Icon.ALIGN_CENTER", }; export const formatAlignmentRight: ActionSpec = { name: _t("Right"), shortcut: "Ctrl+Shift+R", - execute: (env) => ACTIONS.setStyle(env, { align: "right" }), - isActive: (env) => getHorizontalAlign(env) === "right", + execute: (model) => ACTIONS.setStyle(model, { align: "right" }), + isActive: (model) => getHorizontalAlign(model) === "right", icon: "o-spreadsheet-Icon.ALIGN_RIGHT", }; export const formatAlignmentVertical: ActionSpec = { name: _t("Vertical align"), - icon: (env) => getVerticalAlignmentIcon(env), + icon: (model) => getVerticalAlignmentIcon(model), }; export const formatAlignmentTop: ActionSpec = { name: _t("Top"), - execute: (env) => ACTIONS.setStyle(env, { verticalAlign: "top" }), - isActive: (env) => getVerticalAlign(env) === "top", + execute: (model) => ACTIONS.setStyle(model, { verticalAlign: "top" }), + isActive: (model) => getVerticalAlign(model) === "top", icon: "o-spreadsheet-Icon.ALIGN_TOP", }; export const formatAlignmentMiddle: ActionSpec = { name: _t("Middle"), - execute: (env) => ACTIONS.setStyle(env, { verticalAlign: "middle" }), - isActive: (env) => getVerticalAlign(env) === "middle", + execute: (model) => ACTIONS.setStyle(model, { verticalAlign: "middle" }), + isActive: (model) => getVerticalAlign(model) === "middle", icon: "o-spreadsheet-Icon.ALIGN_MIDDLE", }; export const formatAlignmentBottom: ActionSpec = { name: _t("Bottom"), - execute: (env) => ACTIONS.setStyle(env, { verticalAlign: "bottom" }), - isActive: (env) => getVerticalAlign(env) === "bottom", + execute: (model) => ACTIONS.setStyle(model, { verticalAlign: "bottom" }), + isActive: (model) => getVerticalAlign(model) === "bottom", icon: "o-spreadsheet-Icon.ALIGN_BOTTOM", }; @@ -352,27 +350,27 @@ export const formatWrappingIcon: ActionSpec = { export const formatWrapping: ActionSpec = { name: _t("Wrapping"), - icon: (env) => getWrapModeIcon(env), + icon: (model) => getWrapModeIcon(model), }; export const formatWrappingOverflow: ActionSpec = { name: _t("Overflow"), - execute: (env) => ACTIONS.setStyle(env, { wrapping: "overflow" }), - isActive: (env) => getWrappingMode(env) === "overflow", + execute: (model) => ACTIONS.setStyle(model, { wrapping: "overflow" }), + isActive: (model) => getWrappingMode(model) === "overflow", icon: "o-spreadsheet-Icon.WRAPPING_OVERFLOW", }; export const formatWrappingWrap: ActionSpec = { name: _t("Wrap"), - execute: (env) => ACTIONS.setStyle(env, { wrapping: "wrap" }), - isActive: (env) => getWrappingMode(env) === "wrap", + execute: (model) => ACTIONS.setStyle(model, { wrapping: "wrap" }), + isActive: (model) => getWrappingMode(model) === "wrap", icon: "o-spreadsheet-Icon.WRAPPING_WRAP", }; export const formatWrappingClip: ActionSpec = { name: _t("Clip"), - execute: (env) => ACTIONS.setStyle(env, { wrapping: "clip" }), - isActive: (env) => getWrappingMode(env) === "clip", + execute: (model) => ACTIONS.setStyle(model, { wrapping: "clip" }), + isActive: (model) => getWrappingMode(model) === "clip", icon: "o-spreadsheet-Icon.WRAPPING_CLIP", }; @@ -389,7 +387,7 @@ export const fillColor: ActionSpec = { export const formatCF: ActionSpec = { name: _t("Conditional formatting"), execute: ACTIONS.OPEN_CF_SIDEPANEL_ACTION, - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, isEnabledOnLockedSheet: true, icon: "o-spreadsheet-Icon.CONDITIONAL_FORMAT", }; @@ -397,10 +395,10 @@ export const formatCF: ActionSpec = { export const clearFormat: ActionSpec = { name: _t("Clear formatting"), shortcut: "Ctrl+<", - execute: (env) => - env.model.dispatch("CLEAR_FORMATTING", { - sheetId: env.model.getters.getActiveSheetId(), - target: env.model.getters.getSelectedZones(), + execute: (model) => + model.dispatch("CLEAR_FORMATTING", { + sheetId: model.getters.getActiveSheetId(), + target: model.getters.getSelectedZones(), }), icon: "o-spreadsheet-Icon.CLEAR_FORMAT", @@ -412,62 +410,62 @@ function fontSizeMenuBuilder(): ActionSpec[] { name: fs.toString(), sequence: fs, id: `font_size_${fs}`, - execute: (env) => ACTIONS.setStyle(env, { fontSize: fs }), - isActive: (env) => isFontSizeSelected(env, fs), + execute: (model) => ACTIONS.setStyle(model, { fontSize: fs }), + isActive: (model) => isFontSizeSelected(model, fs), }; }); } -function isAutomaticFormatSelected(env: SpreadsheetChildEnv): boolean { - const activePosition = env.model.getters.getActivePosition(); - const pivotCell = env.model.getters.getPivotCellFromPosition(activePosition); +function isAutomaticFormatSelected(model: Model): boolean { + const activePosition = model.getters.getActivePosition(); + const pivotCell = model.getters.getPivotCellFromPosition(activePosition); if (pivotCell.type === "VALUE") { - return !env.model.getters.getEvaluatedCell(activePosition).format; + return !model.getters.getEvaluatedCell(activePosition).format; } - return !env.model.getters.getCell(activePosition)?.format; + return !model.getters.getCell(activePosition)?.format; } -function isFormatSelected(env: SpreadsheetChildEnv, format: string): boolean { - const activePosition = env.model.getters.getActivePosition(); - const pivotCell = env.model.getters.getPivotCellFromPosition(activePosition); +function isFormatSelected(model: Model, format: string): boolean { + const activePosition = model.getters.getActivePosition(); + const pivotCell = model.getters.getPivotCellFromPosition(activePosition); if (pivotCell.type === "VALUE") { - return env.model.getters.getEvaluatedCell(activePosition).format === format; + return model.getters.getEvaluatedCell(activePosition).format === format; } - return env.model.getters.getCell(activePosition)?.format === format; + return model.getters.getCell(activePosition)?.format === format; } -function isFontSizeSelected(env: SpreadsheetChildEnv, fontSize: number): boolean { - const currentFontSize = env.model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE; +function isFontSizeSelected(model: Model, fontSize: number): boolean { + const currentFontSize = model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE; return currentFontSize === fontSize; } -function getHorizontalAlign(env: SpreadsheetChildEnv): Align { - const style = env.model.getters.getCurrentStyle(); +function getHorizontalAlign(model: Model): Align { + const style = model.getters.getCurrentStyle(); if (style.align) { return style.align; } - const cell = env.model.getters.getActiveCell(); + const cell = model.getters.getActiveCell(); return cell.defaultAlign; } -function getVerticalAlign(env: SpreadsheetChildEnv): VerticalAlign { - const style = env.model.getters.getCurrentStyle(); +function getVerticalAlign(model: Model): VerticalAlign { + const style = model.getters.getCurrentStyle(); if (style.verticalAlign) { return style.verticalAlign; } return DEFAULT_VERTICAL_ALIGN; } -function getWrappingMode(env: SpreadsheetChildEnv): Wrapping { - const style = env.model.getters.getCurrentStyle(); +function getWrappingMode(model: Model): Wrapping { + const style = model.getters.getCurrentStyle(); if (style.wrapping) { return style.wrapping; } return DEFAULT_WRAPPING_MODE; } -function getHorizontalAlignmentIcon(env: SpreadsheetChildEnv) { - const horizontalAlign = getHorizontalAlign(env); +function getHorizontalAlignmentIcon(model: Model) { + const horizontalAlign = getHorizontalAlign(model); switch (horizontalAlign) { case "right": @@ -479,8 +477,8 @@ function getHorizontalAlignmentIcon(env: SpreadsheetChildEnv) { } } -function getVerticalAlignmentIcon(env: SpreadsheetChildEnv) { - const verticalAlign = getVerticalAlign(env); +function getVerticalAlignmentIcon(model: Model) { + const verticalAlign = getVerticalAlign(model); switch (verticalAlign) { case "top": @@ -492,8 +490,8 @@ function getVerticalAlignmentIcon(env: SpreadsheetChildEnv) { } } -function getWrapModeIcon(env: SpreadsheetChildEnv) { - const wrapMode = getWrappingMode(env); +function getWrapModeIcon(model: Model) { + const wrapMode = getWrappingMode(model); switch (wrapMode) { case "wrap": @@ -505,14 +503,14 @@ function getWrapModeIcon(env: SpreadsheetChildEnv) { } } -function getRotationIcon(env: SpreadsheetChildEnv) { - if (currentRotationEqual(env, Math.PI / 2)) { +function getRotationIcon(model: Model) { + if (currentRotationEqual(model, Math.PI / 2)) { return "o-spreadsheet-Icon.ROTATION-90"; - } else if (currentRotationEqual(env, -Math.PI / 2)) { + } else if (currentRotationEqual(model, -Math.PI / 2)) { return "o-spreadsheet-Icon.ROTATION-270"; - } else if (currentRotationEqual(env, Math.PI / 4)) { + } else if (currentRotationEqual(model, Math.PI / 4)) { return "o-spreadsheet-Icon.ROTATION-45"; - } else if (currentRotationEqual(env, -Math.PI / 4)) { + } else if (currentRotationEqual(model, -Math.PI / 4)) { return "o-spreadsheet-Icon.ROTATION-315"; } return "o-spreadsheet-Icon.ROTATION-0"; diff --git a/src/actions/insert_actions.ts b/src/actions/insert_actions.ts index 13ebf9df38..3c3eaaa4c0 100644 --- a/src/actions/insert_actions.ts +++ b/src/actions/insert_actions.ts @@ -2,35 +2,36 @@ import { functionRegistry } from "../functions/function_registry"; import { isDefined } from "../helpers/misc"; import { handlePasteResult } from "../helpers/ui/paste_interactive"; import { UuidGenerator } from "../helpers/uuid"; +import { Model } from "../model"; import { _t } from "../translation"; import { ActionBuilder, ActionSpec } from "./action"; import * as ACTIONS from "./menu_items_actions"; export const insertRow: ActionSpec = { - name: (env) => { - const number = getRowsNumber(env); + name: (model) => { + const number = getRowsNumber(model); return number === 1 ? _t("Insert row") : _t("Insert %s rows", number.toString()); }, - isVisible: (env) => ACTIONS.CAN_INSERT_HEADER(env, "ROW"), + isVisible: (model) => ACTIONS.CAN_INSERT_HEADER(model, "ROW"), icon: "o-spreadsheet-Icon.INSERT_ROW", }; export const rowInsertRowBefore: ActionSpec = { - name: (env) => { - const number = getRowsNumber(env); + name: (model) => { + const number = getRowsNumber(model); return number === 1 ? _t("Insert row above") : _t("Insert %s rows above", number.toString()); }, execute: ACTIONS.INSERT_ROWS_BEFORE_ACTION, - isVisible: (env) => ACTIONS.CAN_INSERT_HEADER(env, "ROW"), + isVisible: (model) => ACTIONS.CAN_INSERT_HEADER(model, "ROW"), icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE", }; export const topBarInsertRowsBefore: ActionSpec = { ...rowInsertRowBefore, - name: (env) => { - const number = getRowsNumber(env); + name: (model) => { + const number = getRowsNumber(model); if (number === 1) { return _t("Row above"); } @@ -40,8 +41,8 @@ export const topBarInsertRowsBefore: ActionSpec = { export const cellInsertRowsBefore: ActionSpec = { ...rowInsertRowBefore, - name: (env) => { - const number = getRowsNumber(env); + name: (model) => { + const number = getRowsNumber(model); if (number === 1) { return _t("Insert row"); } @@ -53,19 +54,19 @@ export const cellInsertRowsBefore: ActionSpec = { export const rowInsertRowsAfter: ActionSpec = { execute: ACTIONS.INSERT_ROWS_AFTER_ACTION, - name: (env) => { - const number = getRowsNumber(env); + name: (model) => { + const number = getRowsNumber(model); return number === 1 ? _t("Insert row below") : _t("Insert %s rows below", number.toString()); }, - isVisible: (env) => ACTIONS.CAN_INSERT_HEADER(env, "ROW"), + isVisible: (model) => ACTIONS.CAN_INSERT_HEADER(model, "ROW"), icon: "o-spreadsheet-Icon.INSERT_ROW_AFTER", }; export const topBarInsertRowsAfter: ActionSpec = { ...rowInsertRowsAfter, - name: (env) => { - const number = getRowsNumber(env); + name: (model) => { + const number = getRowsNumber(model); if (number === 1) { return _t("Row below"); } @@ -74,32 +75,32 @@ export const topBarInsertRowsAfter: ActionSpec = { }; export const insertCol: ActionSpec = { - name: (env) => { - const number = getColumnsNumber(env); + name: (model) => { + const number = getColumnsNumber(model); return number === 1 ? _t("Insert column") : _t("Insert %s columns", number.toString()); }, - isVisible: (env) => ACTIONS.CAN_INSERT_HEADER(env, "COL"), + isVisible: (model) => ACTIONS.CAN_INSERT_HEADER(model, "COL"), icon: "o-spreadsheet-Icon.INSERT_COL", }; export const colInsertColsBefore: ActionSpec = { - name: (env) => { - const number = getColumnsNumber(env); + name: (model) => { + const number = getColumnsNumber(model); return number === 1 ? _t("Insert column left") : _t("Insert %s columns left", number.toString()); }, execute: ACTIONS.INSERT_COLUMNS_BEFORE_ACTION, - isVisible: (env) => ACTIONS.CAN_INSERT_HEADER(env, "COL"), + isVisible: (model) => ACTIONS.CAN_INSERT_HEADER(model, "COL"), icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE", }; export const topBarInsertColsBefore: ActionSpec = { ...colInsertColsBefore, - name: (env) => { - const number = getColumnsNumber(env); + name: (model) => { + const number = getColumnsNumber(model); if (number === 1) { return _t("Column left"); } @@ -109,8 +110,8 @@ export const topBarInsertColsBefore: ActionSpec = { export const cellInsertColsBefore: ActionSpec = { ...colInsertColsBefore, - name: (env) => { - const number = getColumnsNumber(env); + name: (model) => { + const number = getColumnsNumber(model); if (number === 1) { return _t("Insert column"); } @@ -121,22 +122,22 @@ export const cellInsertColsBefore: ActionSpec = { }; export const colInsertColsAfter: ActionSpec = { - name: (env) => { - const number = getColumnsNumber(env); + name: (model) => { + const number = getColumnsNumber(model); return number === 1 ? _t("Insert column right") : _t("Insert %s columns right", number.toString()); }, execute: ACTIONS.INSERT_COLUMNS_AFTER_ACTION, - isVisible: (env) => ACTIONS.CAN_INSERT_HEADER(env, "COL"), + isVisible: (model) => ACTIONS.CAN_INSERT_HEADER(model, "COL"), icon: "o-spreadsheet-Icon.INSERT_COL_AFTER", }; export const topBarInsertColsAfter: ActionSpec = { ...colInsertColsAfter, - name: (env) => { - const number = getColumnsNumber(env); + name: (model) => { + const number = getColumnsNumber(model); if (number === 1) { return _t("Column right"); } @@ -147,56 +148,56 @@ export const topBarInsertColsAfter: ActionSpec = { export const insertCell: ActionSpec = { name: _t("Insert cells"), - isVisible: (env) => - ACTIONS.IS_ONLY_ONE_RANGE(env) && - env.model.getters.getActiveCols().size === 0 && - env.model.getters.getActiveRows().size === 0, + isVisible: (model) => + ACTIONS.IS_ONLY_ONE_RANGE(model) && + model.getters.getActiveCols().size === 0 && + model.getters.getActiveRows().size === 0, icon: "o-spreadsheet-Icon.INSERT_CELL", }; export const insertCellShiftDown: ActionSpec = { name: _t("Insert cells and shift down"), - execute: (env) => { - const zone = env.model.getters.getSelectedZone(); - const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "ROW" }); - handlePasteResult(env, result); + execute: (model, env) => { + const zone = model.getters.getSelectedZone(); + const result = model.dispatch("INSERT_CELL", { zone, shiftDimension: "ROW" }); + handlePasteResult(model, env, result); }, - isVisible: (env) => - env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0, + isVisible: (model) => + model.getters.getActiveRows().size === 0 && model.getters.getActiveCols().size === 0, icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_DOWN", }; export const insertCellShiftRight: ActionSpec = { name: _t("Insert cells and shift right"), - execute: (env) => { - const zone = env.model.getters.getSelectedZone(); - const result = env.model.dispatch("INSERT_CELL", { zone, shiftDimension: "COL" }); - handlePasteResult(env, result); + execute: (model, env) => { + const zone = model.getters.getSelectedZone(); + const result = model.dispatch("INSERT_CELL", { zone, shiftDimension: "COL" }); + handlePasteResult(model, env, result); }, - isVisible: (env) => - env.model.getters.getActiveRows().size === 0 && env.model.getters.getActiveCols().size === 0, + isVisible: (model) => + model.getters.getActiveRows().size === 0 && model.getters.getActiveCols().size === 0, icon: "o-spreadsheet-Icon.INSERT_CELL_SHIFT_RIGHT", }; export const insertChart: ActionSpec = { name: _t("Chart"), execute: ACTIONS.CREATE_CHART, - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, icon: "o-spreadsheet-Icon.INSERT_CHART", }; export const insertCarousel: ActionSpec = { name: _t("Carousel"), execute: ACTIONS.CREATE_CAROUSEL, - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, icon: "o-spreadsheet-Icon.CAROUSEL", }; export const insertPivot: ActionSpec = { name: _t("Pivot table"), execute: ACTIONS.CREATE_PIVOT, - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, isEnabledOnLockedSheet: true, icon: "o-spreadsheet-Icon.PIVOT", }; @@ -205,8 +206,8 @@ export const insertImage: ActionSpec = { name: _t("Image"), shortcut: "Ctrl+O", execute: ACTIONS.CREATE_IMAGE, - isVisible: (env) => env.imageProvider !== undefined, - isEnabled: (env) => !env.isSmall, + isVisible: (model, env) => env.imageProvider !== undefined, + isEnabled: (model, env) => !env.isSmall, icon: "o-spreadsheet-Icon.INSERT_IMAGE", }; @@ -214,9 +215,9 @@ export const insertTable: ActionSpec = { name: () => _t("Table"), shortcut: "Alt+T", execute: ACTIONS.INSERT_TABLE, - isVisible: (env) => - ACTIONS.IS_SELECTION_CONTINUOUS(env) && !env.model.getters.getFirstTableInSelection(), - isEnabled: (env) => !env.isSmall, + isVisible: (model) => + ACTIONS.IS_SELECTION_CONTINUOUS(model) && !model.getters.getFirstTableInSelection(), + isEnabled: (model, env) => !env.isSmall, icon: "o-spreadsheet-Icon.PAINT_TABLE", }; @@ -227,27 +228,27 @@ export const insertFunction: ActionSpec = { export const insertFunctionSum: ActionSpec = { name: _t("SUM"), - execute: (env) => env.startCellEdition(`=SUM(`), + execute: (model, env) => env.startCellEdition(`=SUM(`), }; export const insertFunctionAverage: ActionSpec = { name: _t("AVERAGE"), - execute: (env) => env.startCellEdition(`=AVERAGE(`), + execute: (model, env) => env.startCellEdition(`=AVERAGE(`), }; export const insertFunctionCount: ActionSpec = { name: _t("COUNT"), - execute: (env) => env.startCellEdition(`=COUNT(`), + execute: (model, env) => env.startCellEdition(`=COUNT(`), }; export const insertFunctionMax: ActionSpec = { name: _t("MAX"), - execute: (env) => env.startCellEdition(`=MAX(`), + execute: (model, env) => env.startCellEdition(`=MAX(`), }; export const insertFunctionMin: ActionSpec = { name: _t("MIN"), - execute: (env) => env.startCellEdition(`=MIN(`), + execute: (model, env) => env.startCellEdition(`=MIN(`), }; export const categorieFunctionAll: ActionSpec = { @@ -292,11 +293,11 @@ export const insertLink: ActionSpec = { export const insertCheckbox: ActionSpec = { name: _t("Checkbox"), - execute: (env) => { - const zones = env.model.getters.getSelectedZones(); - const sheetId = env.model.getters.getActiveSheetId(); - const ranges = zones.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone)); - env.model.dispatch("ADD_DATA_VALIDATION_RULE", { + execute: (model) => { + const zones = model.getters.getSelectedZones(); + const sheetId = model.getters.getActiveSheetId(); + const ranges = zones.map((zone) => model.getters.getRangeDataFromZone(sheetId, zone)); + model.dispatch("ADD_DATA_VALIDATION_RULE", { ranges, sheetId, rule: { @@ -314,12 +315,12 @@ export const insertCheckbox: ActionSpec = { export const insertDropdown: ActionSpec = { name: _t("Dropdown list"), - execute: (env) => { - const zones = env.model.getters.getSelectedZones(); - const sheetId = env.model.getters.getActiveSheetId(); - const ranges = zones.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone)); + execute: (model, env) => { + const zones = model.getters.getSelectedZones(); + const sheetId = model.getters.getActiveSheetId(); + const ranges = zones.map((zone) => model.getters.getRangeDataFromZone(sheetId, zone)); const ruleId = UuidGenerator.smallUuid(); - env.model.dispatch("ADD_DATA_VALIDATION_RULE", { + model.dispatch("ADD_DATA_VALIDATION_RULE", { ranges, sheetId, rule: { @@ -331,34 +332,34 @@ export const insertDropdown: ActionSpec = { }, }, }); - const rule = env.model.getters.getDataValidationRule(sheetId, ruleId); + const rule = model.getters.getDataValidationRule(sheetId, ruleId); if (!rule) { return; } env.openSidePanel("DataValidationEditor", { ruleId, onCancel: () => { - env.model.dispatch("REMOVE_DATA_VALIDATION_RULE", { sheetId, id: ruleId }); + model.dispatch("REMOVE_DATA_VALIDATION_RULE", { sheetId, id: ruleId }); }, }); }, - isEnabled: (env) => !env.isSmall, + isEnabled: (model, env) => !env.isSmall, icon: "o-spreadsheet-Icon.INSERT_DROPDOWN", }; export const insertSheet: ActionSpec = { name: _t("Insert sheet"), shortcut: "Shift+F11", - execute: (env) => { - const activeSheetId = env.model.getters.getActiveSheetId(); - const position = env.model.getters.getSheetIds().indexOf(activeSheetId) + 1; + execute: (model) => { + const activeSheetId = model.getters.getActiveSheetId(); + const position = model.getters.getSheetIds().indexOf(activeSheetId) + 1; const sheetId = UuidGenerator.smallUuid(); - env.model.dispatch("CREATE_SHEET", { + model.dispatch("CREATE_SHEET", { sheetId, position, - name: env.model.getters.getNextSheetName(), + name: model.getters.getNextSheetName(), }); - env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId }); + model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId }); }, icon: "o-spreadsheet-Icon.INSERT_SHEET", }; @@ -368,27 +369,27 @@ function createFormulaFunctions(fnNames: string[]): ActionSpec[] { return { name: fnName, sequence: i * 10, - execute: (env) => env.startCellEdition(`=${fnName}(`), + execute: (model, env) => env.startCellEdition(`=${fnName}(`), }; }); } -function getRowsNumber(env): number { - const activeRows = env.model.getters.getActiveRows(); +function getRowsNumber(model: Model): number { + const activeRows = model.getters.getActiveRows(); if (activeRows.size) { return activeRows.size; } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; return zone.bottom - zone.top + 1; } } -function getColumnsNumber(env): number { - const activeCols = env.model.getters.getActiveCols(); +function getColumnsNumber(model: Model): number { + const activeCols = model.getters.getActiveCols(); if (activeCols.size) { return activeCols.size; } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; return zone.right - zone.left + 1; } } diff --git a/src/actions/menu_items_actions.ts b/src/actions/menu_items_actions.ts index 3023adfcca..b1516675a3 100644 --- a/src/actions/menu_items_actions.ts +++ b/src/actions/menu_items_actions.ts @@ -18,6 +18,7 @@ import { interactivePaste, interactivePasteFromOS } from "../helpers/ui/paste_in import { interactiveCreateTable } from "../helpers/ui/table_interactive"; import { UuidGenerator } from "../helpers/uuid"; import { areZonesContinuous, getZoneArea, isEqual } from "../helpers/zones"; +import { Model } from "../model"; import { _t } from "../translation"; import { ClipboardMIMEType, ClipboardPasteOptions } from "../types/clipboard"; import { Format } from "../types/format"; @@ -29,18 +30,18 @@ import { ActionSpec } from "./action"; // Helpers //------------------------------------------------------------------------------ -export function setFormatter(env: SpreadsheetChildEnv, format: Format) { - env.model.dispatch("SET_FORMATTING_WITH_PIVOT", { - sheetId: env.model.getters.getActiveSheetId(), - target: env.model.getters.getSelectedZones(), +export function setFormatter(model: Model, format: Format) { + model.dispatch("SET_FORMATTING_WITH_PIVOT", { + sheetId: model.getters.getActiveSheetId(), + target: model.getters.getSelectedZones(), format, }); } -export function setStyle(env: SpreadsheetChildEnv, style: Style) { - env.model.dispatch("SET_FORMATTING", { - sheetId: env.model.getters.getActiveSheetId(), - target: env.model.getters.getSelectedZones(), +export function setStyle(model: Model, style: Style) { + model.dispatch("SET_FORMATTING", { + sheetId: model.getters.getActiveSheetId(), + target: model.getters.getSelectedZones(), style, }); } @@ -49,25 +50,26 @@ export function setStyle(env: SpreadsheetChildEnv, style: Style) { // Simple actions //------------------------------------------------------------------------------ -export const PASTE_ACTION = async (env: SpreadsheetChildEnv) => paste(env); -export const PASTE_AS_VALUE_ACTION = async (env: SpreadsheetChildEnv) => paste(env, "asValue"); +export const PASTE_ACTION = async (model: Model, env: SpreadsheetChildEnv) => paste(model, env); +export const PASTE_AS_VALUE_ACTION = async (model: Model, env: SpreadsheetChildEnv) => + paste(model, env, "asValue"); -async function paste(env: SpreadsheetChildEnv, pasteOption?: ClipboardPasteOptions) { +async function paste(model: Model, env: SpreadsheetChildEnv, pasteOption?: ClipboardPasteOptions) { const osClipboard = await env.clipboard.read(); switch (osClipboard.status) { case "ok": - const clipboardId = env.model.getters.getClipboardId(); - const target = env.model.getters.getSelectedZones(); + const clipboardId = model.getters.getClipboardId(); + const target = model.getters.getSelectedZones(); const htmlClipboardId = getOSheetClipboardIdFromHTML( osClipboard.content[ClipboardMIMEType.Html] ); if (clipboardId === htmlClipboardId) { - interactivePaste(env, target, pasteOption); + interactivePaste(model, env, target, pasteOption); } else { const osClipboardContent = parseOSClipboardContent(osClipboard.content); - await interactivePasteFromOS(env, target, osClipboardContent, pasteOption); + await interactivePasteFromOS(model, env, target, osClipboardContent, pasteOption); } - if (env.model.getters.isCutOperation() && pasteOption !== "asValue") { + if (model.getters.isCutOperation() && pasteOption !== "asValue") { await env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" }); } break; @@ -88,24 +90,25 @@ async function paste(env: SpreadsheetChildEnv, pasteOption?: ClipboardPasteOptio } } -export const PASTE_FORMAT_ACTION = (env: SpreadsheetChildEnv) => paste(env, "onlyFormat"); +export const PASTE_FORMAT_ACTION = (model: Model, env: SpreadsheetChildEnv) => + paste(model, env, "onlyFormat"); //------------------------------------------------------------------------------ // Grid manipulations //------------------------------------------------------------------------------ -export const DELETE_CONTENT_ROWS_NAME = (env: SpreadsheetChildEnv) => { - if (env.model.getters.getSelectedZones().length > 1) { +export const DELETE_CONTENT_ROWS_NAME = (model: Model) => { + if (model.getters.getSelectedZones().length > 1) { return _t("Clear rows"); } let first: number; let last: number; - const activesRows = env.model.getters.getActiveRows(); + const activesRows = model.getters.getActiveRows(); if (activesRows.size !== 0) { first = largeMin([...activesRows]); last = largeMax([...activesRows]); } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; first = zone.top; last = zone.bottom; } @@ -115,29 +118,29 @@ export const DELETE_CONTENT_ROWS_NAME = (env: SpreadsheetChildEnv) => { return _t("Clear rows %s - %s", (first + 1).toString(), (last + 1).toString()); }; -export const DELETE_CONTENT_ROWS_ACTION = (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const target = [...env.model.getters.getActiveRows()].map((index) => - env.model.getters.getRowsZone(sheetId, index, index) +export const DELETE_CONTENT_ROWS_ACTION = (model: Model) => { + const sheetId = model.getters.getActiveSheetId(); + const target = [...model.getters.getActiveRows()].map((index) => + model.getters.getRowsZone(sheetId, index, index) ); - env.model.dispatch("DELETE_CONTENT", { + model.dispatch("DELETE_CONTENT", { target, - sheetId: env.model.getters.getActiveSheetId(), + sheetId: model.getters.getActiveSheetId(), }); }; -export const DELETE_CONTENT_COLUMNS_NAME = (env: SpreadsheetChildEnv) => { - if (env.model.getters.getSelectedZones().length > 1) { +export const DELETE_CONTENT_COLUMNS_NAME = (model: Model) => { + if (model.getters.getSelectedZones().length > 1) { return _t("Clear columns"); } let first: number; let last: number; - const activeCols = env.model.getters.getActiveCols(); + const activeCols = model.getters.getActiveCols(); if (activeCols.size !== 0) { first = largeMin([...activeCols]); last = largeMax([...activeCols]); } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; first = zone.left; last = zone.right; } @@ -147,29 +150,29 @@ export const DELETE_CONTENT_COLUMNS_NAME = (env: SpreadsheetChildEnv) => { return _t("Clear columns %s - %s", numberToLetters(first), numberToLetters(last)); }; -export const DELETE_CONTENT_COLUMNS_ACTION = (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const target = [...env.model.getters.getActiveCols()].map((index) => - env.model.getters.getColsZone(sheetId, index, index) +export const DELETE_CONTENT_COLUMNS_ACTION = (model: Model) => { + const sheetId = model.getters.getActiveSheetId(); + const target = [...model.getters.getActiveCols()].map((index) => + model.getters.getColsZone(sheetId, index, index) ); - env.model.dispatch("DELETE_CONTENT", { + model.dispatch("DELETE_CONTENT", { target, - sheetId: env.model.getters.getActiveSheetId(), + sheetId: model.getters.getActiveSheetId(), }); }; -export const REMOVE_ROWS_NAME = (env: SpreadsheetChildEnv) => { - if (env.model.getters.getSelectedZones().length > 1) { +export const REMOVE_ROWS_NAME = (model: Model) => { + if (model.getters.getSelectedZones().length > 1) { return _t("Delete rows"); } let first: number; let last: number; - const activesRows = env.model.getters.getActiveRows(); + const activesRows = model.getters.getActiveRows(); if (activesRows.size !== 0) { first = largeMin([...activesRows]); last = largeMax([...activesRows]); } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; first = zone.top; last = zone.bottom; } @@ -179,41 +182,38 @@ export const REMOVE_ROWS_NAME = (env: SpreadsheetChildEnv) => { return _t("Delete rows %s - %s", (first + 1).toString(), (last + 1).toString()); }; -export const REMOVE_ROWS_ACTION = (env: SpreadsheetChildEnv) => { - const rows = [...env.model.getters.getActiveRows()]; +export const REMOVE_ROWS_ACTION = (model: Model) => { + const rows = [...model.getters.getActiveRows()]; if (!rows.length) { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; for (let i = zone.top; i <= zone.bottom; i++) { rows.push(i); } } - env.model.dispatch("REMOVE_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), - sheetName: env.model.getters.getActiveSheetName(), + model.dispatch("REMOVE_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), + sheetName: model.getters.getActiveSheetName(), dimension: "ROW", elements: rows, }); }; -export const CAN_REMOVE_COLUMNS_ROWS = ( - dimension: Dimension, - env: SpreadsheetChildEnv -): boolean => { +export const CAN_REMOVE_COLUMNS_ROWS = (model: Model, dimension: Dimension): boolean => { if ( - (dimension === "COL" && env.model.getters.getActiveRows().size > 0) || - (dimension === "ROW" && env.model.getters.getActiveCols().size > 0) + (dimension === "COL" && model.getters.getActiveRows().size > 0) || + (dimension === "ROW" && model.getters.getActiveCols().size > 0) ) { return false; } - const sheetId = env.model.getters.getActiveSheetId(); - const selectedElements = env.model.getters.getElementsFromSelection(dimension); + const sheetId = model.getters.getActiveSheetId(); + const selectedElements = model.getters.getElementsFromSelection(dimension); - const includesAllVisibleHeaders = env.model.getters.checkElementsIncludeAllVisibleHeaders( + const includesAllVisibleHeaders = model.getters.checkElementsIncludeAllVisibleHeaders( sheetId, dimension, selectedElements ); - const includesAllNonFrozenHeaders = env.model.getters.checkElementsIncludeAllNonFrozenHeaders( + const includesAllNonFrozenHeaders = model.getters.checkElementsIncludeAllNonFrozenHeaders( sheetId, dimension, selectedElements @@ -222,18 +222,18 @@ export const CAN_REMOVE_COLUMNS_ROWS = ( return !includesAllVisibleHeaders && !includesAllNonFrozenHeaders; }; -export const REMOVE_COLUMNS_NAME = (env: SpreadsheetChildEnv) => { - if (env.model.getters.getSelectedZones().length > 1) { +export const REMOVE_COLUMNS_NAME = (model: Model) => { + if (model.getters.getSelectedZones().length > 1) { return _t("Delete columns"); } let first: number; let last: number; - const activeCols = env.model.getters.getActiveCols(); + const activeCols = model.getters.getActiveCols(); if (activeCols.size !== 0) { first = largeMin([...activeCols]); last = largeMax([...activeCols]); } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; first = zone.left; last = zone.right; } @@ -243,49 +243,49 @@ export const REMOVE_COLUMNS_NAME = (env: SpreadsheetChildEnv) => { return _t("Delete columns %s - %s", numberToLetters(first), numberToLetters(last)); }; -export const NOT_ALL_VISIBLE_ROWS_SELECTED = (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const selectedRows = env.model.getters.getElementsFromSelection("ROW"); - return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "ROW", selectedRows); +export const NOT_ALL_VISIBLE_ROWS_SELECTED = (model: Model) => { + const sheetId = model.getters.getActiveSheetId(); + const selectedRows = model.getters.getElementsFromSelection("ROW"); + return !model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "ROW", selectedRows); }; -export const REMOVE_COLUMNS_ACTION = (env: SpreadsheetChildEnv) => { - const columns = [...env.model.getters.getActiveCols()]; +export const REMOVE_COLUMNS_ACTION = (model: Model) => { + const columns = [...model.getters.getActiveCols()]; if (!columns.length) { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; for (let i = zone.left; i <= zone.right; i++) { columns.push(i); } } - env.model.dispatch("REMOVE_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), - sheetName: env.model.getters.getActiveSheetName(), + model.dispatch("REMOVE_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), + sheetName: model.getters.getActiveSheetName(), dimension: "COL", elements: columns, }); }; -export const NOT_ALL_VISIBLE_COLS_SELECTED = (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const selectedCols = env.model.getters.getElementsFromSelection("COL"); - return !env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "COL", selectedCols); +export const NOT_ALL_VISIBLE_COLS_SELECTED = (model: Model) => { + const sheetId = model.getters.getActiveSheetId(); + const selectedCols = model.getters.getElementsFromSelection("COL"); + return !model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, "COL", selectedCols); }; -export const INSERT_ROWS_BEFORE_ACTION = (env: SpreadsheetChildEnv) => { - const activeRows = env.model.getters.getActiveRows(); +export const INSERT_ROWS_BEFORE_ACTION = (model: Model) => { + const activeRows = model.getters.getActiveRows(); let row: number; let quantity: number; if (activeRows.size) { row = largeMin([...activeRows]); quantity = activeRows.size; } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; row = zone.top; quantity = zone.bottom - zone.top + 1; } - env.model.dispatch("ADD_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), - sheetName: env.model.getters.getActiveSheetName(), + model.dispatch("ADD_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), + sheetName: model.getters.getActiveSheetName(), position: "before", base: row, quantity, @@ -293,21 +293,21 @@ export const INSERT_ROWS_BEFORE_ACTION = (env: SpreadsheetChildEnv) => { }); }; -export const INSERT_ROWS_AFTER_ACTION = (env: SpreadsheetChildEnv) => { - const activeRows = env.model.getters.getActiveRows(); +export const INSERT_ROWS_AFTER_ACTION = (model: Model) => { + const activeRows = model.getters.getActiveRows(); let row: number; let quantity: number; if (activeRows.size) { row = largeMax([...activeRows]); quantity = activeRows.size; } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; row = zone.bottom; quantity = zone.bottom - zone.top + 1; } - env.model.dispatch("ADD_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), - sheetName: env.model.getters.getActiveSheetName(), + model.dispatch("ADD_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), + sheetName: model.getters.getActiveSheetName(), position: "after", base: row, quantity, @@ -315,21 +315,21 @@ export const INSERT_ROWS_AFTER_ACTION = (env: SpreadsheetChildEnv) => { }); }; -export const INSERT_COLUMNS_BEFORE_ACTION = (env: SpreadsheetChildEnv) => { - const activeCols = env.model.getters.getActiveCols(); +export const INSERT_COLUMNS_BEFORE_ACTION = (model: Model) => { + const activeCols = model.getters.getActiveCols(); let column: number; let quantity: number; if (activeCols.size) { column = largeMin([...activeCols]); quantity = activeCols.size; } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; column = zone.left; quantity = zone.right - zone.left + 1; } - env.model.dispatch("ADD_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), - sheetName: env.model.getters.getActiveSheetName(), + model.dispatch("ADD_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), + sheetName: model.getters.getActiveSheetName(), position: "before", dimension: "COL", base: column, @@ -337,21 +337,21 @@ export const INSERT_COLUMNS_BEFORE_ACTION = (env: SpreadsheetChildEnv) => { }); }; -export const INSERT_COLUMNS_AFTER_ACTION = (env: SpreadsheetChildEnv) => { - const activeCols = env.model.getters.getActiveCols(); +export const INSERT_COLUMNS_AFTER_ACTION = (model: Model) => { + const activeCols = model.getters.getActiveCols(); let column: number; let quantity: number; if (activeCols.size) { column = largeMax([...activeCols]); quantity = activeCols.size; } else { - const zone = env.model.getters.getSelectedZones()[0]; + const zone = model.getters.getSelectedZones()[0]; column = zone.right; quantity = zone.right - zone.left + 1; } - env.model.dispatch("ADD_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), - sheetName: env.model.getters.getActiveSheetName(), + model.dispatch("ADD_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), + sheetName: model.getters.getActiveSheetName(), position: "after", dimension: "COL", base: column, @@ -359,8 +359,8 @@ export const INSERT_COLUMNS_AFTER_ACTION = (env: SpreadsheetChildEnv) => { }); }; -export const HIDE_COLUMNS_NAME = (env: SpreadsheetChildEnv) => { - const cols = env.model.getters.getElementsFromSelection("COL"); +export const HIDE_COLUMNS_NAME = (model: Model) => { + const cols = model.getters.getElementsFromSelection("COL"); const first = cols[0]; const last = cols[cols.length - 1]; if (cols.length === 1) { @@ -376,8 +376,8 @@ export const HIDE_COLUMNS_NAME = (env: SpreadsheetChildEnv) => { } }; -export const HIDE_ROWS_NAME = (env: SpreadsheetChildEnv) => { - const rows = env.model.getters.getElementsFromSelection("ROW"); +export const HIDE_ROWS_NAME = (model: Model) => { + const rows = model.getters.getElementsFromSelection("ROW"); const first = rows[0]; const last = rows[rows.length - 1]; if (rows.length === 1) { @@ -393,21 +393,21 @@ export const HIDE_ROWS_NAME = (env: SpreadsheetChildEnv) => { // Charts //------------------------------------------------------------------------------ -export const CREATE_CHART = (env: SpreadsheetChildEnv) => { - const getters = env.model.getters; +export const CREATE_CHART = (model: Model, env: SpreadsheetChildEnv) => { + const getters = model.getters; const figureId = UuidGenerator.smallUuid(); const sheetId = getters.getActiveSheetId(); let zones = getters.getSelectedZones(); if (zones.length === 1 && getZoneArea(zones[0]) === 1) { - env.model.selection.selectTableAroundSelection(); + model.selection.selectTableAroundSelection(); zones = getters.getSelectedZones(); } const size = { width: DEFAULT_FIGURE_WIDTH, height: DEFAULT_FIGURE_HEIGHT }; const { col, row, offset } = centerFigurePosition(getters, size); - const result = env.model.dispatch("CREATE_CHART", { + const result = model.dispatch("CREATE_CHART", { sheetId, figureId, chartId: UuidGenerator.smallUuid(), @@ -415,23 +415,23 @@ export const CREATE_CHART = (env: SpreadsheetChildEnv) => { row, offset, size, - definition: getSmartChartDefinition(zones, env.model.getters), + definition: getSmartChartDefinition(zones, model.getters), }); if (result.isSuccessful) { - env.model.dispatch("SELECT_FIGURE", { figureId }); + model.dispatch("SELECT_FIGURE", { figureId }); env.openSidePanel("ChartPanel"); } }; -export const CREATE_CAROUSEL = (env: SpreadsheetChildEnv) => { - const getters = env.model.getters; +export const CREATE_CAROUSEL = (model: Model, env: SpreadsheetChildEnv) => { + const getters = model.getters; const figureId = UuidGenerator.smallUuid(); const sheetId = getters.getActiveSheetId(); const size = { width: DEFAULT_FIGURE_WIDTH, height: DEFAULT_FIGURE_HEIGHT }; const { col, row, offset } = centerFigurePosition(getters, size); - const result = env.model.dispatch("CREATE_CAROUSEL", { + const result = model.dispatch("CREATE_CAROUSEL", { sheetId, figureId, col, @@ -441,7 +441,7 @@ export const CREATE_CAROUSEL = (env: SpreadsheetChildEnv) => { definition: { items: [] }, }); if (result.isSuccessful) { - env.model.dispatch("SELECT_FIGURE", { figureId }); + model.dispatch("SELECT_FIGURE", { figureId }); env.openSidePanel("CarouselPanel", { figureId }); } }; @@ -450,77 +450,77 @@ export const CREATE_CAROUSEL = (env: SpreadsheetChildEnv) => { // Pivots //------------------------------------------------------------------------------ -export const CREATE_PIVOT = (env: SpreadsheetChildEnv) => { +export const CREATE_PIVOT = (model: Model, env: SpreadsheetChildEnv) => { const pivotId = UuidGenerator.smallUuid(); const newSheetId = UuidGenerator.smallUuid(); - const result = env.model.dispatch("INSERT_NEW_PIVOT", { pivotId, newSheetId }); + const result = model.dispatch("INSERT_NEW_PIVOT", { pivotId, newSheetId }); if (result.isSuccessful) { env.openSidePanel("PivotSidePanel", { pivotId }); } }; -export const REINSERT_DYNAMIC_PIVOT_CHILDREN = (env: SpreadsheetChildEnv) => - env.model.getters.getPivotIds().map((pivotId, index) => ({ - id: `reinsert_dynamic_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`, - name: env.model.getters.getPivotDisplayName(pivotId), +export const REINSERT_DYNAMIC_PIVOT_CHILDREN = (model: Model) => + model.getters.getPivotIds().map((pivotId, index) => ({ + id: `reinsert_dynamic_pivot_${model.getters.getPivotFormulaId(pivotId)}`, + name: model.getters.getPivotDisplayName(pivotId), sequence: index, - execute: (env: SpreadsheetChildEnv) => { - const zone = env.model.getters.getSelectedZone(); - const table = env.model.getters.getPivot(pivotId).getCollapsedTableStructure().export(); - env.model.dispatch("INSERT_PIVOT_WITH_TABLE", { + execute: (model: Model) => { + const zone = model.getters.getSelectedZone(); + const table = model.getters.getPivot(pivotId).getCollapsedTableStructure().export(); + model.dispatch("INSERT_PIVOT_WITH_TABLE", { pivotId, table, col: zone.left, row: zone.top, - sheetId: env.model.getters.getActiveSheetId(), + sheetId: model.getters.getActiveSheetId(), pivotMode: "dynamic", }); - env.model.dispatch("REFRESH_PIVOT", { id: pivotId }); + model.dispatch("REFRESH_PIVOT", { id: pivotId }); }, - isVisible: (env: SpreadsheetChildEnv) => env.model.getters.getPivot(pivotId).isValid(), + isVisible: (model: Model) => model.getters.getPivot(pivotId).isValid(), })); -export const REINSERT_STATIC_PIVOT_CHILDREN = (env: SpreadsheetChildEnv) => - env.model.getters.getPivotIds().map((pivotId, index) => ({ - id: `reinsert_static_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`, - name: env.model.getters.getPivotDisplayName(pivotId), +export const REINSERT_STATIC_PIVOT_CHILDREN = (model: Model) => + model.getters.getPivotIds().map((pivotId, index) => ({ + id: `reinsert_static_pivot_${model.getters.getPivotFormulaId(pivotId)}`, + name: model.getters.getPivotDisplayName(pivotId), sequence: index, - execute: (env: SpreadsheetChildEnv) => { - const zone = env.model.getters.getSelectedZone(); - const table = env.model.getters.getPivot(pivotId).getExpandedTableStructure(); + execute: (model: Model, env: SpreadsheetChildEnv) => { + const zone = model.getters.getSelectedZone(); + const table = model.getters.getPivot(pivotId).getExpandedTableStructure(); if (table.numberOfCells > PIVOT_MAX_NUMBER_OF_CELLS) { env.notifyUser({ type: "warning", - text: getPivotTooBigErrorMessage(table.numberOfCells, env.model.getters.getLocale()), + text: getPivotTooBigErrorMessage(table.numberOfCells, model.getters.getLocale()), sticky: true, }); return; } - env.model.dispatch("INSERT_PIVOT_WITH_TABLE", { + model.dispatch("INSERT_PIVOT_WITH_TABLE", { pivotId, table: table.export(), col: zone.left, row: zone.top, - sheetId: env.model.getters.getActiveSheetId(), + sheetId: model.getters.getActiveSheetId(), pivotMode: "static", }); - env.model.dispatch("REFRESH_PIVOT", { id: pivotId }); + model.dispatch("REFRESH_PIVOT", { id: pivotId }); }, - isVisible: (env: SpreadsheetChildEnv) => env.model.getters.getPivot(pivotId).isValid(), + isVisible: (model: Model) => model.getters.getPivot(pivotId).isValid(), })); //------------------------------------------------------------------------------ // Image //------------------------------------------------------------------------------ -export const CREATE_IMAGE = async (env: SpreadsheetChildEnv) => { +export const CREATE_IMAGE = async (model: Model, env: SpreadsheetChildEnv) => { if (env.imageProvider) { - const sheetId = env.model.getters.getActiveSheetId(); + const sheetId = model.getters.getActiveSheetId(); const figureId = UuidGenerator.smallUuid(); const image = await env.imageProvider.requestImage(); - const size = getMaxFigureSize(env.model.getters, image.size); - const { col, row, offset } = centerFigurePosition(env.model.getters, size); - env.model.dispatch("CREATE_IMAGE", { + const size = getMaxFigureSize(model.getters, image.size); + const { col, row, offset } = centerFigurePosition(model.getters, size); + model.dispatch("CREATE_IMAGE", { sheetId, figureId, col, @@ -536,16 +536,16 @@ export const CREATE_IMAGE = async (env: SpreadsheetChildEnv) => { // Style/Format //------------------------------------------------------------------------------ -export const FORMAT_PERCENT_ACTION = (env: SpreadsheetChildEnv) => setFormatter(env, "0.00%"); +export const FORMAT_PERCENT_ACTION = (model: Model) => setFormatter(model, "0.00%"); //------------------------------------------------------------------------------ // Side panel //------------------------------------------------------------------------------ -export const OPEN_CF_SIDEPANEL_ACTION = (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const zones = env.model.getters.getSelectedZones(); - const rules = env.model.getters.getConditionalFormats(sheetId); - const ruleIds = env.model.getters.getRulesSelection(sheetId, zones); +export const OPEN_CF_SIDEPANEL_ACTION = (model: Model, env: SpreadsheetChildEnv) => { + const sheetId = model.getters.getActiveSheetId(); + const zones = model.getters.getSelectedZones(); + const rules = model.getters.getConditionalFormats(sheetId); + const ruleIds = model.getters.getRulesSelection(sheetId, zones); if (ruleIds.length === 1) { return env.openSidePanel("ConditionalFormattingEditor", { cf: rules.find((r) => r.id === ruleIds[0]), @@ -555,15 +555,15 @@ export const OPEN_CF_SIDEPANEL_ACTION = (env: SpreadsheetChildEnv) => { return env.openSidePanel("ConditionalFormatting"); }; -export const INSERT_LINK = (env: SpreadsheetChildEnv) => { - const { col, row } = env.model.getters.getActivePosition(); +export const INSERT_LINK = (model: Model, env: SpreadsheetChildEnv) => { + const { col, row } = model.getters.getActivePosition(); env.getStore(CellPopoverStore).open({ col, row }, "LinkEditor"); }; -export const INSERT_LINK_NAME = (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const { col, row } = env.model.getters.getActivePosition(); - const cell = env.model.getters.getEvaluatedCell({ sheetId, col, row }); +export const INSERT_LINK_NAME = (model: Model, env: SpreadsheetChildEnv) => { + const sheetId = model.getters.getActiveSheetId(); + const { col, row } = model.getters.getActivePosition(); + const cell = model.getters.getEvaluatedCell({ sheetId, col, row }); return cell && cell.link ? _t("Edit link") : _t("Insert link"); }; @@ -572,27 +572,27 @@ export const INSERT_LINK_NAME = (env: SpreadsheetChildEnv) => { // Filters action //------------------------------------------------------------------------------ -export const SELECTED_TABLE_HAS_FILTERS = (env: SpreadsheetChildEnv): boolean => { - const table = env.model.getters.getFirstTableInSelection(); +export const SELECTED_TABLE_HAS_FILTERS = (model: Model): boolean => { + const table = model.getters.getFirstTableInSelection(); return table?.config.hasFilters || false; }; -export const SELECTION_CONTAINS_SINGLE_TABLE = (env: SpreadsheetChildEnv): boolean => { - const sheetId = env.model.getters.getActiveSheetId(); - const selectedZones = env.model.getters.getSelectedZones(); - const tables = env.model.getters.getTablesOverlappingZones(sheetId, selectedZones); +export const SELECTION_CONTAINS_SINGLE_TABLE = (model: Model): boolean => { + const sheetId = model.getters.getActiveSheetId(); + const selectedZones = model.getters.getSelectedZones(); + const tables = model.getters.getTablesOverlappingZones(sheetId, selectedZones); return tables.length === 1 && !tables[0].isPivotTable; }; -export const IS_SELECTION_CONTINUOUS = (env: SpreadsheetChildEnv): boolean => { - return areZonesContinuous(env.model.getters.getSelectedZones()); +export const IS_SELECTION_CONTINUOUS = (model: Model): boolean => { + return areZonesContinuous(model.getters.getSelectedZones()); }; -export const ADD_DATA_FILTER = (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const table = env.model.getters.getFirstTableInSelection(); +export const ADD_DATA_FILTER = (model: Model, env: SpreadsheetChildEnv) => { + const sheetId = model.getters.getActiveSheetId(); + const table = model.getters.getFirstTableInSelection(); if (table) { - env.model.dispatch("UPDATE_TABLE", { + model.dispatch("UPDATE_TABLE", { sheetId, zone: table.range.zone, config: { hasFilters: true }, @@ -604,39 +604,39 @@ export const ADD_DATA_FILTER = (env: SpreadsheetChildEnv) => { bandedRows: false, styleId: "TableStyleLight11", }; - interactiveCreateTable(env, sheetId, tableConfig); + interactiveCreateTable(model, env, sheetId, tableConfig); } }; -export const REMOVE_DATA_FILTER = (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const table = env.model.getters.getFirstTableInSelection(); +export const REMOVE_DATA_FILTER = (model: Model) => { + const sheetId = model.getters.getActiveSheetId(); + const table = model.getters.getFirstTableInSelection(); if (!table) { return; } - env.model.dispatch("UPDATE_TABLE", { + model.dispatch("UPDATE_TABLE", { sheetId, zone: table.range.zone, config: { hasFilters: false }, }); }; -export const INSERT_TABLE = (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); +export const INSERT_TABLE = (model: Model, env: SpreadsheetChildEnv) => { + const sheetId = model.getters.getActiveSheetId(); - const result = interactiveCreateTable(env, sheetId); + const result = interactiveCreateTable(model, env, sheetId); if (result.isSuccessful) { env.openSidePanel("TableSidePanel", {}); } }; -export const DELETE_SELECTED_TABLE = (env: SpreadsheetChildEnv) => { - const table = env.model.getters.getFirstTableInSelection(); +export const DELETE_SELECTED_TABLE = (model: Model) => { + const table = model.getters.getFirstTableInSelection(); if (!table) { return; } - env.model.dispatch("REMOVE_TABLE", { - sheetId: env.model.getters.getActiveSheetId(), + model.dispatch("REMOVE_TABLE", { + sheetId: model.getters.getActiveSheetId(), target: [table.range.zone], }); }; @@ -645,29 +645,29 @@ export const DELETE_SELECTED_TABLE = (env: SpreadsheetChildEnv) => { // Sorting action //------------------------------------------------------------------------------ -export const IS_ONLY_ONE_RANGE = (env: SpreadsheetChildEnv): boolean => { - return env.model.getters.getSelectedZones().length === 1; +export const IS_ONLY_ONE_RANGE = (model: Model): boolean => { + return model.getters.getSelectedZones().length === 1; }; -export const CAN_INSERT_HEADER = (env: SpreadsheetChildEnv, dimension: Dimension): boolean => { - if (!IS_ONLY_ONE_RANGE(env)) { +export const CAN_INSERT_HEADER = (model: Model, dimension: Dimension): boolean => { + if (!IS_ONLY_ONE_RANGE(model)) { return false; } const activeHeaders = - dimension === "COL" ? env.model.getters.getActiveCols() : env.model.getters.getActiveRows(); + dimension === "COL" ? model.getters.getActiveCols() : model.getters.getActiveRows(); const ortogonalActiveHeaders = - dimension === "COL" ? env.model.getters.getActiveRows() : env.model.getters.getActiveCols(); - const sheetId = env.model.getters.getActiveSheetId(); - const zone = env.model.getters.getSelectedZone(); - const allSheetSelected = isEqual(zone, env.model.getters.getSheetZone(sheetId)); + dimension === "COL" ? model.getters.getActiveRows() : model.getters.getActiveCols(); + const sheetId = model.getters.getActiveSheetId(); + const zone = model.getters.getSelectedZone(); + const allSheetSelected = isEqual(zone, model.getters.getSheetZone(sheetId)); return isConsecutive(activeHeaders) && (ortogonalActiveHeaders.size === 0 || allSheetSelected); }; export const CREATE_OR_REMOVE_FILTER_ACTION: ActionSpec = { - name: (env) => - SELECTED_TABLE_HAS_FILTERS(env) ? _t("Remove selected filters") : _t("Add filters"), - isEnabled: (env) => IS_SELECTION_CONTINUOUS(env), - execute: (env) => - SELECTED_TABLE_HAS_FILTERS(env) ? REMOVE_DATA_FILTER(env) : ADD_DATA_FILTER(env), + name: (model) => + SELECTED_TABLE_HAS_FILTERS(model) ? _t("Remove selected filters") : _t("Add filters"), + isEnabled: (model) => IS_SELECTION_CONTINUOUS(model), + execute: (model, env) => + SELECTED_TABLE_HAS_FILTERS(model) ? REMOVE_DATA_FILTER(model) : ADD_DATA_FILTER(model, env), icon: "o-spreadsheet-Icon.FILTER_ICON_ACTIVE", }; diff --git a/src/actions/sheet_actions.ts b/src/actions/sheet_actions.ts index b553d4dfc3..3f71a8e9d9 100644 --- a/src/actions/sheet_actions.ts +++ b/src/actions/sheet_actions.ts @@ -6,10 +6,8 @@ import { ActionSpec } from "./action"; export const linkSheet: ActionSpec = { name: _t("Link sheet"), children: [ - (env) => { - const sheets = env.model.getters - .getSheetIds() - .map((sheetId) => env.model.getters.getSheet(sheetId)); + (model) => { + const sheets = model.getters.getSheetIds().map((sheetId) => model.getters.getSheet(sheetId)); return sheets.map((sheet) => ({ id: sheet.id, name: sheet.name, @@ -21,15 +19,15 @@ export const linkSheet: ActionSpec = { export const deleteSheet: ActionSpec = { name: _t("Delete"), - isVisible: (env) => { - return env.model.getters.getVisibleSheetIds().length > 1; + isVisible: (model) => { + return model.getters.getVisibleSheetIds().length > 1; }, - execute: (env) => + execute: (model, env) => env.askConfirmation(_t("Are you sure you want to delete this sheet?"), () => { - env.model.dispatch("DELETE_SHEET", { - sheetId: env.model.getters.getActiveSheetId(), - sheetName: env.model.getters.getActiveSheetName(), + model.dispatch("DELETE_SHEET", { + sheetId: model.getters.getActiveSheetId(), + sheetName: model.getters.getActiveSheetName(), }); }), icon: "o-spreadsheet-Icon.TRASH", @@ -37,17 +35,17 @@ export const deleteSheet: ActionSpec = { export const duplicateSheet: ActionSpec = { name: _t("Duplicate"), - execute: (env) => { - const sheetIdFrom = env.model.getters.getActiveSheetId(); - const sheetNameFrom = env.model.getters.getSheetName(sheetIdFrom); + execute: (model, env) => { + const sheetIdFrom = model.getters.getActiveSheetId(); + const sheetNameFrom = model.getters.getSheetName(sheetIdFrom); const sheetIdTo = UuidGenerator.smallUuid(); - const sheetNameTo = env.model.getters.getDuplicateSheetName(sheetNameFrom); - env.model.dispatch("DUPLICATE_SHEET", { + const sheetNameTo = model.getters.getDuplicateSheetName(sheetNameFrom); + model.dispatch("DUPLICATE_SHEET", { sheetId: sheetIdFrom, sheetIdTo, sheetNameTo, }); - env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo }); + model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo }); }, isEnabledOnLockedSheet: true, icon: "o-spreadsheet-Icon.COPY", @@ -73,14 +71,14 @@ export const changeSheetColor = (args: { export const sheetMoveRight: ActionSpec = { name: _t("Move right"), - isVisible: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - const sheetIds = env.model.getters.getVisibleSheetIds(); + isVisible: (model) => { + const sheetId = model.getters.getActiveSheetId(); + const sheetIds = model.getters.getVisibleSheetIds(); return sheetIds.indexOf(sheetId) !== sheetIds.length - 1; }, - execute: (env) => - env.model.dispatch("MOVE_SHEET", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => + model.dispatch("MOVE_SHEET", { + sheetId: model.getters.getActiveSheetId(), delta: 1, }), isEnabledOnLockedSheet: true, @@ -89,13 +87,13 @@ export const sheetMoveRight: ActionSpec = { export const sheetMoveLeft: ActionSpec = { name: _t("Move left"), - isVisible: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - return env.model.getters.getVisibleSheetIds()[0] !== sheetId; + isVisible: (model) => { + const sheetId = model.getters.getActiveSheetId(); + return model.getters.getVisibleSheetIds()[0] !== sheetId; }, - execute: (env) => - env.model.dispatch("MOVE_SHEET", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => + model.dispatch("MOVE_SHEET", { + sheetId: model.getters.getActiveSheetId(), delta: -1, }), isEnabledOnLockedSheet: true, @@ -104,21 +102,20 @@ export const sheetMoveLeft: ActionSpec = { export const hideSheet: ActionSpec = { name: _t("Hide sheet"), - isVisible: (env) => env.model.getters.getVisibleSheetIds().length !== 1, - execute: (env) => - env.model.dispatch("HIDE_SHEET", { sheetId: env.model.getters.getActiveSheetId() }), + isVisible: (model) => model.getters.getVisibleSheetIds().length !== 1, + execute: (model) => model.dispatch("HIDE_SHEET", { sheetId: model.getters.getActiveSheetId() }), isEnabledOnLockedSheet: true, icon: "o-spreadsheet-Icon.HIDE_SHEET", }; export const lockSheet: ActionSpec = { name: _t("Lock sheet"), - isVisible: (env) => { - return !env.model.getters.isCurrentSheetLocked(); + isVisible: (model) => { + return !model.getters.isCurrentSheetLocked(); }, - execute: (env) => { - env.model.dispatch("LOCK_SHEET", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => { + model.dispatch("LOCK_SHEET", { + sheetId: model.getters.getActiveSheetId(), }); }, icon: "o-spreadsheet-Icon.LOCK", @@ -126,12 +123,12 @@ export const lockSheet: ActionSpec = { export const unlockSheet: ActionSpec = { name: _t("Unlock sheet"), - isVisible: (env) => { - return env.model.getters.isCurrentSheetLocked(); + isVisible: (model) => { + return model.getters.isCurrentSheetLocked(); }, - execute: (env) => { - env.model.dispatch("UNLOCK_SHEET", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => { + model.dispatch("UNLOCK_SHEET", { + sheetId: model.getters.getActiveSheetId(), }); }, isEnabledOnLockedSheet: true, diff --git a/src/actions/view_actions.ts b/src/actions/view_actions.ts index a48725a6ad..313a838ebd 100644 --- a/src/actions/view_actions.ts +++ b/src/actions/view_actions.ts @@ -1,19 +1,19 @@ import { SidePanelStore } from "../components/side_panel/side_panel/side_panel_store"; import { numberToLetters } from "../helpers/coordinates"; import { interactiveFreezeColumnsRows } from "../helpers/ui/freeze_interactive"; +import { Model } from "../model"; import { FormulaFingerprintStore } from "../stores/formula_fingerprints_store"; import { _t } from "../translation"; import { Dimension } from "../types/misc"; -import { SpreadsheetChildEnv } from "../types/spreadsheet_env"; import { ActionSpec } from "./action"; import * as ACTIONS from "./menu_items_actions"; export const hideCols: ActionSpec = { name: ACTIONS.HIDE_COLUMNS_NAME, - execute: (env) => { - const columns = env.model.getters.getElementsFromSelection("COL"); - env.model.dispatch("HIDE_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => { + const columns = model.getters.getElementsFromSelection("COL"); + model.dispatch("HIDE_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), dimension: "COL", elements: columns, }); @@ -25,19 +25,17 @@ export const hideCols: ActionSpec = { export const unhideCols: ActionSpec = { name: _t("Unhide columns"), - execute: (env) => { - const columns = env.model.getters.getElementsFromSelection("COL"); - env.model.dispatch("UNHIDE_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => { + const columns = model.getters.getElementsFromSelection("COL"); + model.dispatch("UNHIDE_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), dimension: "COL", elements: columns, }); }, - isVisible: (env: SpreadsheetChildEnv) => { - const hiddenCols = env.model.getters - .getHiddenColsGroups(env.model.getters.getActiveSheetId()) - .flat(); - const currentCols = env.model.getters.getElementsFromSelection("COL"); + isVisible: (model: Model) => { + const hiddenCols = model.getters.getHiddenColsGroups(model.getters.getActiveSheetId()).flat(); + const currentCols = model.getters.getElementsFromSelection("COL"); return currentCols.some((col) => hiddenCols.includes(col)); }, @@ -46,26 +44,26 @@ export const unhideCols: ActionSpec = { export const unhideAllCols: ActionSpec = { name: _t("Unhide all columns"), - execute: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - env.model.dispatch("UNHIDE_COLUMNS_ROWS", { + execute: (model) => { + const sheetId = model.getters.getActiveSheetId(); + model.dispatch("UNHIDE_COLUMNS_ROWS", { sheetId, dimension: "COL", - elements: Array.from(Array(env.model.getters.getNumberCols(sheetId)).keys()), + elements: Array.from(Array(model.getters.getNumberCols(sheetId)).keys()), }); }, - isVisible: (env: SpreadsheetChildEnv) => - env.model.getters.getHiddenColsGroups(env.model.getters.getActiveSheetId()).length > 0, + isVisible: (model: Model) => + model.getters.getHiddenColsGroups(model.getters.getActiveSheetId()).length > 0, icon: "o-spreadsheet-Icon.UNHIDE_COL", }; export const hideRows: ActionSpec = { name: ACTIONS.HIDE_ROWS_NAME, - execute: (env) => { - const rows = env.model.getters.getElementsFromSelection("ROW"); - env.model.dispatch("HIDE_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => { + const rows = model.getters.getElementsFromSelection("ROW"); + model.dispatch("HIDE_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), dimension: "ROW", elements: rows, }); @@ -77,19 +75,17 @@ export const hideRows: ActionSpec = { export const unhideRows: ActionSpec = { name: _t("Unhide rows"), - execute: (env) => { - const columns = env.model.getters.getElementsFromSelection("ROW"); - env.model.dispatch("UNHIDE_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => { + const columns = model.getters.getElementsFromSelection("ROW"); + model.dispatch("UNHIDE_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), dimension: "ROW", elements: columns, }); }, - isVisible: (env: SpreadsheetChildEnv) => { - const hiddenRows = env.model.getters - .getHiddenRowsGroups(env.model.getters.getActiveSheetId()) - .flat(); - const currentRows = env.model.getters.getElementsFromSelection("ROW"); + isVisible: (model: Model) => { + const hiddenRows = model.getters.getHiddenRowsGroups(model.getters.getActiveSheetId()).flat(); + const currentRows = model.getters.getElementsFromSelection("ROW"); return currentRows.some((col) => hiddenRows.includes(col)); }, @@ -98,31 +94,29 @@ export const unhideRows: ActionSpec = { export const unhideAllRows: ActionSpec = { name: _t("Unhide all rows"), - execute: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - env.model.dispatch("UNHIDE_COLUMNS_ROWS", { + execute: (model) => { + const sheetId = model.getters.getActiveSheetId(); + model.dispatch("UNHIDE_COLUMNS_ROWS", { sheetId, dimension: "ROW", - elements: Array.from(Array(env.model.getters.getNumberRows(sheetId)).keys()), + elements: Array.from(Array(model.getters.getNumberRows(sheetId)).keys()), }); }, - isVisible: (env: SpreadsheetChildEnv) => - env.model.getters.getHiddenRowsGroups(env.model.getters.getActiveSheetId()).length > 0, + isVisible: (model: Model) => + model.getters.getHiddenRowsGroups(model.getters.getActiveSheetId()).length > 0, icon: "o-spreadsheet-Icon.UNHIDE_ROW", }; export const unFreezePane: ActionSpec = { name: _t("Unfreeze"), - isVisible: (env) => { - const { xSplit, ySplit } = env.model.getters.getPaneDivisions( - env.model.getters.getActiveSheetId() - ); + isVisible: (model) => { + const { xSplit, ySplit } = model.getters.getPaneDivisions(model.getters.getActiveSheetId()); return xSplit + ySplit > 0; }, - execute: (env) => - env.model.dispatch("UNFREEZE_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => + model.dispatch("UNFREEZE_COLUMNS_ROWS", { + sheetId: model.getters.getActiveSheetId(), }), icon: "o-spreadsheet-Icon.UNFREEZE", @@ -135,78 +129,76 @@ export const freezePane: ActionSpec = { export const unFreezeRows: ActionSpec = { name: _t("No rows"), - execute: (env) => - env.model.dispatch("UNFREEZE_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => + model.dispatch("UNFREEZE_ROWS", { + sheetId: model.getters.getActiveSheetId(), }), - isVisible: (env) => - !!env.model.getters.getPaneDivisions(env.model.getters.getActiveSheetId()).ySplit, + isVisible: (model) => !!model.getters.getPaneDivisions(model.getters.getActiveSheetId()).ySplit, }; export const freezeFirstRow: ActionSpec = { name: _t("1 row"), - execute: (env) => interactiveFreezeColumnsRows(env, "ROW", 1), + execute: (model, env) => interactiveFreezeColumnsRows(model, env, "ROW", 1), }; export const freezeSecondRow: ActionSpec = { name: _t("2 rows"), - execute: (env) => interactiveFreezeColumnsRows(env, "ROW", 2), + execute: (model, env) => interactiveFreezeColumnsRows(model, env, "ROW", 2), }; export const freezeCurrentRow: ActionSpec = { name: _t("Up to current row"), - execute: (env) => { - const { bottom } = env.model.getters.getSelectedZone(); - interactiveFreezeColumnsRows(env, "ROW", bottom + 1); + execute: (model, env) => { + const { bottom } = model.getters.getSelectedZone(); + interactiveFreezeColumnsRows(model, env, "ROW", bottom + 1); }, }; export const unFreezeCols: ActionSpec = { name: _t("No columns"), - execute: (env) => - env.model.dispatch("UNFREEZE_COLUMNS", { - sheetId: env.model.getters.getActiveSheetId(), + execute: (model) => + model.dispatch("UNFREEZE_COLUMNS", { + sheetId: model.getters.getActiveSheetId(), }), - isVisible: (env) => - !!env.model.getters.getPaneDivisions(env.model.getters.getActiveSheetId()).xSplit, + isVisible: (model) => !!model.getters.getPaneDivisions(model.getters.getActiveSheetId()).xSplit, }; export const freezeFirstCol: ActionSpec = { name: _t("1 column"), - execute: (env) => interactiveFreezeColumnsRows(env, "COL", 1), + execute: (model, env) => interactiveFreezeColumnsRows(model, env, "COL", 1), }; export const freezeSecondCol: ActionSpec = { name: _t("2 columns"), - execute: (env) => interactiveFreezeColumnsRows(env, "COL", 2), + execute: (model, env) => interactiveFreezeColumnsRows(model, env, "COL", 2), }; export const freezeCurrentCol: ActionSpec = { name: _t("Up to current column"), - execute: (env) => { - const { right } = env.model.getters.getSelectedZone(); - interactiveFreezeColumnsRows(env, "COL", right + 1); + execute: (model, env) => { + const { right } = model.getters.getSelectedZone(); + interactiveFreezeColumnsRows(model, env, "COL", right + 1); }, }; export const viewGridlines: ActionSpec = { name: _t("Gridlines"), - execute: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - env.model.dispatch("SET_GRID_LINES_VISIBILITY", { + execute: (model) => { + const sheetId = model.getters.getActiveSheetId(); + model.dispatch("SET_GRID_LINES_VISIBILITY", { sheetId, - areGridLinesVisible: !env.model.getters.getGridLinesVisibility(sheetId), + areGridLinesVisible: !model.getters.getGridLinesVisibility(sheetId), }); }, - isActive: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - return env.model.getters.getGridLinesVisibility(sheetId); + isActive: (model) => { + const sheetId = model.getters.getActiveSheetId(); + return model.getters.getGridLinesVisibility(sheetId); }, }; export const irregularityMap: ActionSpec = { name: _t("Irregularity map"), - execute: (env) => { + execute: (model, env) => { const fingerprintStore = env.getStore(FormulaFingerprintStore); if (fingerprintStore.isEnabled) { fingerprintStore.disable(); @@ -222,10 +214,10 @@ export const irregularityMap: ActionSpec = { export function zoomAction(zoom: number): ActionSpec { return { name: _t("%(zoom_percentage)s%", { zoom_percentage: zoom }), - execute: (env) => { - env.model.dispatch("SET_ZOOM", { zoom: zoom / 100 }); + execute: (model) => { + model.dispatch("SET_ZOOM", { zoom: zoom / 100 }); }, - isActive: (env: SpreadsheetChildEnv) => env.model.getters.getViewportZoomLevel() === zoom / 100, + isActive: (model: Model) => model.getters.getViewportZoomLevel() === zoom / 100, isReadonlyAllowed: true, isEnabledOnLockedSheet: true, sequence: zoom, @@ -234,16 +226,16 @@ export function zoomAction(zoom: number): ActionSpec { export const viewFormulas: ActionSpec = { name: _t("Formulas"), - isActive: (env: SpreadsheetChildEnv) => env.model.getters.shouldShowFormulas(), - execute: (env) => - env.model.dispatch("SET_FORMULA_VISIBILITY", { show: !env.model.getters.shouldShowFormulas() }), + isActive: (model: Model) => model.getters.shouldShowFormulas(), + execute: (model) => + model.dispatch("SET_FORMULA_VISIBILITY", { show: !model.getters.shouldShowFormulas() }), isReadonlyAllowed: true, isEnabledOnLockedSheet: true, }; export const groupColumns: ActionSpec = { - name: (env) => { - const selection = env.model.getters.getSelectedZone(); + name: (model) => { + const selection = model.getters.getSelectedZone(); if (selection.left === selection.right) { return _t("Group column %s", numberToLetters(selection.left)); } @@ -253,14 +245,14 @@ export const groupColumns: ActionSpec = { numberToLetters(selection.right) ); }, - execute: (env) => groupHeadersAction(env, "COL"), - isVisible: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - const selection = env.model.getters.getSelectedZone(); - const groups = env.model.getters.getHeaderGroupsInZone(sheetId, "COL", selection); + execute: (model) => groupHeadersAction(model, "COL"), + isVisible: (model) => { + const sheetId = model.getters.getActiveSheetId(); + const selection = model.getters.getSelectedZone(); + const groups = model.getters.getHeaderGroupsInZone(sheetId, "COL", selection); return ( - ACTIONS.IS_ONLY_ONE_RANGE(env) && + ACTIONS.IS_ONLY_ONE_RANGE(model) && !groups.some((group) => group.start === selection.left && group.end === selection.right) ); }, @@ -269,21 +261,21 @@ export const groupColumns: ActionSpec = { }; export const groupRows: ActionSpec = { - name: (env) => { - const selection = env.model.getters.getSelectedZone(); + name: (model) => { + const selection = model.getters.getSelectedZone(); if (selection.top === selection.bottom) { return _t("Group row %s", String(selection.top + 1)); } return _t("Group rows %s - %s", String(selection.top + 1), String(selection.bottom + 1)); }, - execute: (env) => groupHeadersAction(env, "ROW"), - isVisible: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - const selection = env.model.getters.getSelectedZone(); - const groups = env.model.getters.getHeaderGroupsInZone(sheetId, "ROW", selection); + execute: (model) => groupHeadersAction(model, "ROW"), + isVisible: (model) => { + const sheetId = model.getters.getActiveSheetId(); + const selection = model.getters.getSelectedZone(); + const groups = model.getters.getHeaderGroupsInZone(sheetId, "ROW", selection); return ( - ACTIONS.IS_ONLY_ONE_RANGE(env) && + ACTIONS.IS_ONLY_ONE_RANGE(model) && !groups.some((group) => group.start === selection.top && group.end === selection.bottom) ); }, @@ -292,8 +284,8 @@ export const groupRows: ActionSpec = { }; export const ungroupColumns: ActionSpec = { - name: (env) => { - const selection = env.model.getters.getSelectedZone(); + name: (model) => { + const selection = model.getters.getSelectedZone(); if (selection.left === selection.right) { return _t("Ungroup column %s", numberToLetters(selection.left)); } @@ -303,28 +295,28 @@ export const ungroupColumns: ActionSpec = { numberToLetters(selection.right) ); }, - execute: (env) => ungroupHeaders(env, "COL"), + execute: (model) => ungroupHeaders(model, "COL"), icon: "o-spreadsheet-Icon.UNGROUP_COLUMNS", }; export const ungroupRows: ActionSpec = { - name: (env) => { - const selection = env.model.getters.getSelectedZone(); + name: (model) => { + const selection = model.getters.getSelectedZone(); if (selection.top === selection.bottom) { return _t("Ungroup row %s", String(selection.top + 1)); } return _t("Ungroup rows %s - %s", String(selection.top + 1), String(selection.bottom + 1)); }, - execute: (env) => ungroupHeaders(env, "ROW"), + execute: (model) => ungroupHeaders(model, "ROW"), icon: "o-spreadsheet-Icon.UNGROUP_ROWS", }; -function groupHeadersAction(env: SpreadsheetChildEnv, dim: Dimension) { - const selection = env.model.getters.getSelectedZone(); - const sheetId = env.model.getters.getActiveSheetId(); - env.model.dispatch("GROUP_HEADERS", { +function groupHeadersAction(model: Model, dim: Dimension) { + const selection = model.getters.getSelectedZone(); + const sheetId = model.getters.getActiveSheetId(); + model.dispatch("GROUP_HEADERS", { sheetId, dimension: dim, start: dim === "COL" ? selection.left : selection.top, @@ -332,10 +324,10 @@ function groupHeadersAction(env: SpreadsheetChildEnv, dim: Dimension) { }); } -function ungroupHeaders(env: SpreadsheetChildEnv, dim: Dimension) { - const selection = env.model.getters.getSelectedZone(); - const sheetId = env.model.getters.getActiveSheetId(); - env.model.dispatch("UNGROUP_HEADERS", { +function ungroupHeaders(model: Model, dim: Dimension) { + const selection = model.getters.getSelectedZone(); + const sheetId = model.getters.getActiveSheetId(); + model.dispatch("UNGROUP_HEADERS", { sheetId, dimension: dim, start: dim === "COL" ? selection.left : selection.top, @@ -343,26 +335,26 @@ function ungroupHeaders(env: SpreadsheetChildEnv, dim: Dimension) { }); } -export function canUngroupHeaders(env: SpreadsheetChildEnv, dimension: Dimension): boolean { - const sheetId = env.model.getters.getActiveSheetId(); - const selection = env.model.getters.getSelectedZones(); +export function canUngroupHeaders(model: Model, dimension: Dimension): boolean { + const sheetId = model.getters.getActiveSheetId(); + const selection = model.getters.getSelectedZones(); return ( selection.length === 1 && - env.model.getters.getHeaderGroupsInZone(sheetId, dimension, selection[0]).length > 0 + model.getters.getHeaderGroupsInZone(sheetId, dimension, selection[0]).length > 0 ); } export const togglePinPanel: ActionSpec = { - name: (env) => { + name: (model, env) => { const sidepanelStore = env.getStore(SidePanelStore); return sidepanelStore.mainPanel && sidepanelStore.mainPanel.isPinned ? _t("Unpin the side panel") : _t("Pin the side panel"); }, - isVisible: (env) => { + isVisible: (model, env) => { return env.getStore(SidePanelStore).isMainPanelOpen; }, - execute: (env) => { + execute: (model, env) => { env.getStore(SidePanelStore).togglePinPanel(); }, icon: "o-spreadsheet-Icon.THUMB_TACK", diff --git a/src/components/action_button/action_button.ts b/src/components/action_button/action_button.ts index 5fd94127ba..9bd079f82d 100644 --- a/src/components/action_button/action_button.ts +++ b/src/components/action_button/action_button.ts @@ -4,6 +4,7 @@ import { Component } from "../../owl3_compatibility_layer"; import { PropsOf } from "../../types/props_of"; import { SpreadsheetChildEnv } from "../../types/spreadsheet_env"; import { cssPropertiesToCss } from "../helpers/css"; +import { useModel } from "../owl_plugins/model_plugin"; import { types } from "../props_validation"; export class ActionButton extends Component { @@ -19,6 +20,7 @@ export class ActionButton extends Component { private actionButton = createAction(this.props.action); + private model = useModel(); setup() { onWillUpdateProps((nextProps: PropsOf) => { if (nextProps.action !== this.props.action) { @@ -28,33 +30,34 @@ export class ActionButton extends Component { } get isVisible() { - return this.actionButton.isVisible(this.env); + return this.actionButton.isVisible(this.model(), this.env); } get isEnabled() { const isLockedAvailable = - this.actionButton.isEnabledOnLockedSheet || !this.env.model.getters.isCurrentSheetLocked(); - return this.actionButton.isEnabled(this.env) && isLockedAvailable; + this.actionButton.isEnabledOnLockedSheet || !this.model().getters.isCurrentSheetLocked(); + return this.actionButton.isEnabled(this.model(), this.env) && isLockedAvailable; } get isActive() { - return this.actionButton.isActive?.(this.env); + return this.actionButton.isActive?.(this.model(), this.env); } get title() { - const name = this.actionButton.name(this.env); - const description = this.actionButton.description(this.env) || this.actionButton.shortcut; + const name = this.actionButton.name(this.model(), this.env); + const description = + this.actionButton.description(this.model(), this.env) || this.actionButton.shortcut; return name + (description ? ` (${description})` : ""); } get iconTitle() { - return this.actionButton.icon(this.env); + return this.actionButton.icon(this.model(), this.env); } onClick(ev: MouseEvent) { if (this.isEnabled) { this.props.onClick?.(ev); - this.actionButton.execute?.(this.env); + this.actionButton.execute?.(this.model(), this.env); } } diff --git a/src/components/autofill/autofill.ts b/src/components/autofill/autofill.ts index 8b70df2755..c781b87423 100644 --- a/src/components/autofill/autofill.ts +++ b/src/components/autofill/autofill.ts @@ -7,6 +7,7 @@ import { SpreadsheetChildEnv } from "../../types/spreadsheet_env"; import { cssPropertiesToCss } from "../helpers/css"; import { useDragAndDropBeyondTheViewport } from "../helpers/drag_and_drop_grid_hook"; import { withZoom } from "../helpers/zoom"; +import { useModel } from "../owl_plugins/model_plugin"; import { types } from "../props_validation"; // ----------------------------------------------------------------------------- @@ -25,12 +26,13 @@ export class Autofill extends Component { position: types.DOMCoordinates(), isVisible: types.boolean(), }); + private model = useModel(); state: State = proxy({ position: { x: 0, y: 0 }, handler: false, }); - dragNDropGrid = useDragAndDropBeyondTheViewport(this.env); + dragNDropGrid = useDragAndDropBeyondTheViewport(this.model()); get style() { const { x, y } = this.props.position; @@ -57,7 +59,7 @@ export class Autofill extends Component { } getTooltip() { - const tooltip = this.env.model.getters.getAutofillTooltip(); + const tooltip = this.model().getters.getAutofillTooltip(); if (tooltip && !tooltip.component) { tooltip.component = TooltipComponent; } @@ -66,8 +68,8 @@ export class Autofill extends Component { onMouseDown(ev: PointerEvent) { this.state.handler = true; - const zoomedMouseEvent = withZoom(this.env, ev); - const zoom = this.env.model.getters.getViewportZoomLevel(); + const zoomedMouseEvent = withZoom(this.model(), ev); + const zoom = this.model().getters.getViewportZoomLevel(); let lastCol: HeaderIndex | undefined; let lastRow: HeaderIndex | undefined; const start = { @@ -77,7 +79,7 @@ export class Autofill extends Component { const onMouseUp = () => { this.state.handler = false; this.state.position = { ...this.props.position }; - this.env.model.dispatch("AUTOFILL"); + this.model().dispatch("AUTOFILL"); }; const onMouseMove = (col: HeaderIndex, row: HeaderIndex, ev: MouseEvent) => { @@ -86,13 +88,13 @@ export class Autofill extends Component { y: ev.clientY / zoom - start.y, }; if (lastCol !== col || lastRow !== row) { - const activeSheetId = this.env.model.getters.getActiveSheetId(); - const numberOfCols = this.env.model.getters.getNumberCols(activeSheetId); - const numberOfRows = this.env.model.getters.getNumberRows(activeSheetId); + const activeSheetId = this.model().getters.getActiveSheetId(); + const numberOfCols = this.model().getters.getNumberCols(activeSheetId); + const numberOfRows = this.model().getters.getNumberRows(activeSheetId); lastCol = col === -1 ? lastCol : clip(col, 0, numberOfCols); lastRow = row === -1 ? lastRow : clip(row, 0, numberOfRows); if (lastCol !== undefined && lastRow !== undefined) { - this.env.model.dispatch("AUTOFILL_SELECT", { col: lastCol, row: lastRow }); + this.model().dispatch("AUTOFILL_SELECT", { col: lastCol, row: lastRow }); } } }; @@ -100,7 +102,7 @@ export class Autofill extends Component { } onDblClick() { - this.env.model.dispatch("AUTOFILL_AUTO"); + this.model().dispatch("AUTOFILL_AUTO"); } } diff --git a/src/components/border_editor/border_editor_widget.ts b/src/components/border_editor/border_editor_widget.ts index c60fd9caf2..6759840512 100644 --- a/src/components/border_editor/border_editor_widget.ts +++ b/src/components/border_editor/border_editor_widget.ts @@ -6,6 +6,7 @@ import { Rect } from "../../types/rendering"; import { SpreadsheetChildEnv } from "../../types/spreadsheet_env"; import { getElBoundingRect } from "../helpers/dom_helpers"; import { ToolBarDropdownStore, useToolBarDropdownStore } from "../helpers/top_bar_tool_hook"; +import { useModel } from "../owl_plugins/model_plugin"; import { types } from "../props_validation"; import { BorderEditor } from "./border_editor"; @@ -33,6 +34,7 @@ export class BorderEditorWidget extends Component { currentPosition: undefined, }); + private model = useModel(); setup() { this.topBarToolStore = useToolBarDropdownStore(); onWillUpdateProps(() => { @@ -43,7 +45,7 @@ export class BorderEditorWidget extends Component { } get dropdownMaxHeight(): Pixel { - return this.env.model.getters.getSheetViewDimension().height; + return this.model().getters.getSheetViewDimension().height; } get borderEditorAnchorRect(): Rect { @@ -81,9 +83,9 @@ export class BorderEditorWidget extends Component { if (this.state.currentPosition === undefined) { return; } - this.env.model.dispatch("SET_ZONE_BORDERS", { - sheetId: this.env.model.getters.getActiveSheetId(), - target: this.env.model.getters.getSelectedZones(), + this.model().dispatch("SET_ZONE_BORDERS", { + sheetId: this.model().getters.getActiveSheetId(), + target: this.model().getters.getSelectedZones(), border: { position: this.state.currentPosition, color: this.state.currentColor, diff --git a/src/components/border_editor/border_editor_widget.xml b/src/components/border_editor/border_editor_widget.xml index b9ae9fd394..5195645109 100644 --- a/src/components/border_editor/border_editor_widget.xml +++ b/src/components/border_editor/border_editor_widget.xml @@ -2,7 +2,7 @@
{ menuItems: [], }); - sheetList = this.getVisibleSheets(); + sheetList: BottomBarSheetItem[] = []; + + private model = useModel(); setup() { + this.sheetList = this.getVisibleSheets(); onWillUpdateProps(() => { this.updateScrollState(); const visibleSheets = this.getVisibleSheets(); @@ -69,40 +73,44 @@ export class BottomBar extends Component { } clickAddSheet(ev: MouseEvent) { - const activeSheetId = this.env.model.getters.getActiveSheetId(); + const activeSheetId = this.model().getters.getActiveSheetId(); const position = - this.env.model.getters.getSheetIds().findIndex((sheetId) => sheetId === activeSheetId) + 1; + this.model() + .getters.getSheetIds() + .findIndex((sheetId) => sheetId === activeSheetId) + 1; const sheetId = UuidGenerator.smallUuid(); - const name = this.env.model.getters.getNextSheetName(_t("Sheet")); - this.env.model.dispatch("CREATE_SHEET", { sheetId, position, name }); - this.env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId }); + const name = this.model().getters.getNextSheetName(_t("Sheet")); + this.model().dispatch("CREATE_SHEET", { sheetId, position, name }); + this.model().dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: sheetId }); } getVisibleSheets(): BottomBarSheetItem[] { - return this.env.model.getters.getVisibleSheetIds().map((sheetId) => { - const sheet = this.env.model.getters.getSheet(sheetId); - return { id: sheet.id, name: sheet.name }; - }); + return this.model() + .getters.getVisibleSheetIds() + .map((sheetId) => { + const sheet = this.model().getters.getSheet(sheetId); + return { id: sheet.id, name: sheet.name }; + }); } clickListSheets(ev: MouseEvent) { const registry = new MenuItemRegistry(); - const from = this.env.model.getters.getActiveSheetId(); + const from = this.model().getters.getActiveSheetId(); let i = 0; - for (const sheetId of this.env.model.getters.getSheetIds()) { - const sheet = this.env.model.getters.getSheet(sheetId); + for (const sheetId of this.model().getters.getSheetIds()) { + const sheet = this.model().getters.getSheet(sheetId); registry.add(sheetId, { name: sheet.name, sequence: i, isReadonlyAllowed: true, textColor: sheet.isVisible ? undefined : "#808080", - execute: (env) => { - if (!this.env.model.getters.isSheetVisible(sheetId)) { - this.env.model.dispatch("SHOW_SHEET", { sheetId }); + execute: (model) => { + if (!model.getters.isSheetVisible(sheetId)) { + model.dispatch("SHOW_SHEET", { sheetId }); } - env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: from, sheetIdTo: sheetId }); + model.dispatch("ACTIVATE_SHEET", { sheetIdFrom: from, sheetIdTo: sheetId }); }, - isEnabled: (env) => (env.model.getters.isReadonly() ? sheet.isVisible : true), + isEnabled: (model) => (model.getters.isReadonly() ? sheet.isVisible : true), icon: sheet.color ? "o-spreadsheet-Icon.SMALL_DOT_RIGHT_ALIGN" : undefined, iconColor: sheet.color, isEnabledOnLockedSheet: true, @@ -195,7 +203,7 @@ export class BottomBar extends Component { } onSheetMouseDown(sheetId: UID, event: MouseEvent) { - if (event.button !== 0 || this.env.model.getters.isReadonly()) { + if (event.button !== 0 || this.model().getters.isReadonly()) { return; } this.closeMenu(); @@ -225,7 +233,7 @@ export class BottomBar extends Component { const originalIndex = this.getVisibleSheets().findIndex((sheet) => sheet.id === sheetId); const delta = finalIndex - originalIndex; if (sheetId && delta !== 0) { - this.env.model.dispatch("MOVE_SHEET", { + this.model().dispatch("MOVE_SHEET", { sheetId: sheetId, delta: delta, }); diff --git a/src/components/bottom_bar/bottom_bar.xml b/src/components/bottom_bar/bottom_bar.xml index e0137c2c69..400bf12ab1 100644 --- a/src/components/bottom_bar/bottom_bar.xml +++ b/src/components/bottom_bar/bottom_bar.xml @@ -7,7 +7,7 @@
diff --git a/src/components/bottom_bar/bottom_bar_sheet/bottom_bar_sheet.ts b/src/components/bottom_bar/bottom_bar_sheet/bottom_bar_sheet.ts index 89c67d4cf6..36ca8901de 100644 --- a/src/components/bottom_bar/bottom_bar_sheet/bottom_bar_sheet.ts +++ b/src/components/bottom_bar/bottom_bar_sheet/bottom_bar_sheet.ts @@ -15,6 +15,7 @@ import { Ripple } from "../../animation/ripple"; import { ColorPicker } from "../../color_picker/color_picker"; import { cssPropertiesToCss } from "../../helpers/css"; import { getElBoundingRect } from "../../helpers/dom_helpers"; +import { useModel } from "../../owl_plugins/model_plugin"; interface State { isEditing: boolean; @@ -62,6 +63,7 @@ export class BottomBarSheet extends Component { private editionState: "initializing" | "editing" = "initializing"; + private model = useModel(); private DOMFocusableElementStore!: Store; setup() { this.DOMFocusableElementStore = useStore(DOMFocusableElementStore); @@ -88,7 +90,7 @@ export class BottomBarSheet extends Component { this.scrollToSheet(); } }, - () => [this.env.model.getters.getActiveSheetId()] + () => [this.model().getters.getActiveSheetId()] ); onMounted(() => { @@ -100,7 +102,7 @@ export class BottomBarSheet extends Component { 800 ); - this.env.model.on( + this.model().on( "command-rejected", this, async ({ command, result }: { command: Command; result: DispatchResult }) => { @@ -118,7 +120,7 @@ export class BottomBarSheet extends Component { ); }); onWillUnmount(() => { - this.env.model.off("command-rejected", this); + this.model().off("command-rejected", this); }); } @@ -164,15 +166,15 @@ export class BottomBarSheet extends Component { } private activateSheet() { - this.env.model.dispatch("ACTIVATE_SHEET", { - sheetIdFrom: this.env.model.getters.getActiveSheetId(), + this.model().dispatch("ACTIVATE_SHEET", { + sheetIdFrom: this.model().getters.getActiveSheetId(), sheetIdTo: this.props.sheetId, }); this.scrollToSheet(); } onDblClick() { - if (this.env.model.getters.isReadonly() || this.isSheetLocked) { + if (this.model().getters.isReadonly() || this.isSheetLocked) { return; } this.startEdition(); @@ -215,7 +217,9 @@ export class BottomBarSheet extends Component { const inputValue = this.getInputContent() || ""; - interactiveRenameSheet(this.env, this.props.sheetId, inputValue, () => this.startEdition()); + interactiveRenameSheet(this.model(), this.env, this.props.sheetId, inputValue, () => + this.startEdition() + ); } private cancelEdition() { @@ -256,7 +260,7 @@ export class BottomBarSheet extends Component { onColorPicked(color: string) { this.state.pickerOpened = false; - this.env.model.dispatch("COLOR_SHEET", { sheetId: this.props.sheetId, color }); + this.model().dispatch("COLOR_SHEET", { sheetId: this.props.sheetId, color }); } get colorPickerAnchorRect(): Rect { @@ -277,19 +281,19 @@ export class BottomBarSheet extends Component { } get isSheetActive() { - return this.env.model.getters.getActiveSheetId() === this.props.sheetId; + return this.model().getters.getActiveSheetId() === this.props.sheetId; } get sheetName() { - return this.env.model.getters.getSheetName(this.props.sheetId); + return this.model().getters.getSheetName(this.props.sheetId); } get sheetColorStyle() { - const color = this.env.model.getters.getSheet(this.props.sheetId).color || ""; + const color = this.model().getters.getSheet(this.props.sheetId).color || ""; return cssPropertiesToCss({ background: color }); } get isSheetLocked() { - return this.env.model.getters.isSheetLocked(this.props.sheetId); + return this.model().getters.isSheetLocked(this.props.sheetId); } } diff --git a/src/components/bottom_bar/bottom_bar_statistic/bottom_bar_statistic.ts b/src/components/bottom_bar/bottom_bar_statistic/bottom_bar_statistic.ts index 4187969cbc..39df2bd5cf 100644 --- a/src/components/bottom_bar/bottom_bar_statistic/bottom_bar_statistic.ts +++ b/src/components/bottom_bar/bottom_bar_statistic/bottom_bar_statistic.ts @@ -6,6 +6,7 @@ import { useStore } from "../../../store_engine/store_hooks"; import { SpreadsheetChildEnv } from "../../../types/spreadsheet_env"; import { Store } from "../../../types/store_engine"; import { Ripple } from "../../animation/ripple"; +import { useModel } from "../../owl_plugins/model_plugin"; import { AggregateStatisticsStore } from "./aggregate_statistics_store"; // ----------------------------------------------------------------------------- @@ -28,6 +29,8 @@ export class BottomBarStatistic extends Component { private state = proxy({ selectedStatisticFn: "" }); private store!: Store; + private model = useModel(); + setup() { this.store = useStore(AggregateStatisticsStore); onWillUpdateProps(() => { @@ -72,7 +75,7 @@ export class BottomBarStatistic extends Component { } private getComposedFnName(fnName: string): string { - const locale = this.env.model.getters.getLocale(); + const locale = this.model().getters.getLocale(); const fnValue = this.store.statisticFnResults[fnName]; return ( fnName + diff --git a/src/components/collaborative_client_tag/collaborative_client_tag.ts b/src/components/collaborative_client_tag/collaborative_client_tag.ts index 9eca56436f..d368209f2b 100644 --- a/src/components/collaborative_client_tag/collaborative_client_tag.ts +++ b/src/components/collaborative_client_tag/collaborative_client_tag.ts @@ -1,8 +1,8 @@ -import { SpreadsheetChildEnv } from "../../types/spreadsheet_env"; -import { cssPropertiesToCss } from "../helpers/css"; - import { props } from "@odoo/owl"; import { Component } from "../../owl3_compatibility_layer"; +import { SpreadsheetChildEnv } from "../../types/spreadsheet_env"; +import { cssPropertiesToCss } from "../helpers/css"; +import { useModel } from "../owl_plugins/model_plugin"; import { types } from "../props_validation"; export class ClientTag extends Component { @@ -15,15 +15,18 @@ export class ClientTag extends Component { col: types.HeaderIndex(), row: types.HeaderIndex(), }); + + private model = useModel(); + get tagStyle(): string { const { col, row, color } = this.props; - const { height } = this.env.model.getters.getSheetViewDimensionWithHeaders(); - const visible = this.env.model.getters.isVisibleInViewport({ - sheetId: this.env.model.getters.getActiveSheetId(), + const { height } = this.model().getters.getSheetViewDimensionWithHeaders(); + const visible = this.model().getters.isVisibleInViewport({ + sheetId: this.model().getters.getActiveSheetId(), col, row, }); - const { x, y } = this.env.model.getters.getVisibleRect({ + const { x, y } = this.model().getters.getVisibleRect({ left: col, top: row, right: col, diff --git a/src/components/color_picker/color_picker.ts b/src/components/color_picker/color_picker.ts index 44e665115b..2b43dd908e 100644 --- a/src/components/color_picker/color_picker.ts +++ b/src/components/color_picker/color_picker.ts @@ -16,6 +16,7 @@ import { PropsOf } from "../../types/props_of"; import { SpreadsheetChildEnv } from "../../types/spreadsheet_env"; import { cssPropertiesToCss } from "../helpers/css"; import { startDnd } from "../helpers/drag_and_drop"; +import { useModel } from "../owl_plugins/model_plugin"; import { Popover } from "../popover/popover"; import { types } from "../props_validation"; @@ -62,6 +63,8 @@ export class ColorPicker extends Component { customHexColor: isColorValid(this.props.currentColor) ? toHex(this.props.currentColor) : "", }); + protected model = useModel(); + get colorPickerStyle(): string { if (this.props.maxHeight !== undefined && this.props.maxHeight <= 0) { return cssPropertiesToCss({ display: "none" }); diff --git a/src/components/color_picker/color_picker.xml b/src/components/color_picker/color_picker.xml index 140bb094a2..d2d1c48cc5 100644 --- a/src/components/color_picker/color_picker.xml +++ b/src/components/color_picker/color_picker.xml @@ -33,7 +33,7 @@
{ private DOMFocusableElementStore!: Store; + private model = useModel(); + composerRef = signal(null); containerRef = signal(null); @@ -270,7 +273,7 @@ export class Composer extends Component { // Prevent the default content editable behavior which moves the cursor ev.preventDefault(); ev.stopPropagation(); - updateSelectionWithArrowKeys(ev, this.env.model.selection); + updateSelectionWithArrowKeys(ev, this.model().selection); return; } const content = this.props.composerStore.currentContent; @@ -353,7 +356,7 @@ export class Composer extends Component { private processNumpadDecimal(ev: KeyboardEvent) { ev.stopPropagation(); ev.preventDefault(); - const locale = this.env.model.getters.getLocale(); + const locale = this.model().getters.getLocale(); const selection = this.contentHelper.getCurrentSelection(); const currentContent = this.props.composerStore.currentContent; const content = @@ -504,7 +507,7 @@ export class Composer extends Component { } onMouseup() { - if (this.env.model.getters.isReadonly()) { + if (this.model().getters.isReadonly()) { return; } const selection = this.contentHelper.getCurrentSelection(); @@ -514,7 +517,7 @@ export class Composer extends Component { } onClick() { - if (this.env.model.getters.isReadonly()) { + if (this.model().getters.isReadonly()) { return; } const newSelection = this.contentHelper.getCurrentSelection(); @@ -527,7 +530,7 @@ export class Composer extends Component { } onDblClick() { - if (this.env.model.getters.isReadonly()) { + if (this.model().getters.isReadonly()) { return; } const composerContent = this.props.composerStore.currentContent; diff --git a/src/components/composer/composer/composer.xml b/src/components/composer/composer/composer.xml index ff354181d0..6f0a88bbf1 100644 --- a/src/components/composer/composer/composer.xml +++ b/src/components/composer/composer/composer.xml @@ -21,11 +21,11 @@
isCollapsed: true, }); + private model = useModel(); + toggle() { this.state.isCollapsed = !this.state.isCollapsed; } @@ -29,7 +32,7 @@ export class FunctionDescriptionProvider extends Component get formulaHeaderContent(): { content: string; focused?: boolean }[] { const { functionDescription, repeatingArgGroupIndex, argsToFocus } = this.props; - const argSeparator = this.env.model.getters.getLocale().formulaArgSeparator + " "; + const argSeparator = this.model().getters.getLocale().formulaArgSeparator + " "; const result: { content: string; focused?: boolean }[] = [ { content: functionDescription.name + " ( " }, diff --git a/src/components/composer/grid_composer/grid_composer.ts b/src/components/composer/grid_composer/grid_composer.ts index 9871fdd71e..83aa3afe2c 100644 --- a/src/components/composer/grid_composer/grid_composer.ts +++ b/src/components/composer/grid_composer/grid_composer.ts @@ -13,6 +13,7 @@ import { Rect } from "../../../types/rendering"; import { SpreadsheetChildEnv } from "../../../types/spreadsheet_env"; import { Store } from "../../../types/store_engine"; import { cssPropertiesToCss, getTextDecoration } from "../../helpers/css"; +import { useModel } from "../../owl_plugins/model_plugin"; import { types } from "../../props_validation"; import { CellComposerStore } from "../composer/cell_composer_store"; import { Composer } from "../composer/composer"; @@ -37,12 +38,9 @@ export class GridComposer extends Component { private rect: Rect = this.defaultRect; private isEditing: boolean = false; private isCellReferenceVisible: boolean = false; - private currentEditedCell: CellPosition = { - col: 0, - row: 0, - sheetId: this.env.model.getters.getActiveSheetId(), - }; + private currentEditedCell!: CellPosition; + private model = useModel(); private composerStore!: Store; composerFocusStore!: Store; @@ -53,6 +51,7 @@ export class GridComposer extends Component { } setup() { + this.currentEditedCell = { col: 0, row: 0, sheetId: this.model().getters.getActiveSheetId() }; const composerStore = useStore(CellComposerStore); this.composerStore = composerStore; this.composerFocusStore = useStore(ComposerFocusStore); @@ -78,9 +77,9 @@ export class GridComposer extends Component { get cellReference(): string { const { col, row, sheetId } = this.composerStore.currentEditedCell; - const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId(); + const prefixSheet = sheetId !== this.model().getters.getActiveSheetId(); return getFullReference( - prefixSheet ? this.env.model.getters.getSheetName(sheetId) : undefined, + prefixSheet ? this.model().getters.getSheetName(sheetId) : undefined, toXC(col, row) ); } @@ -100,7 +99,7 @@ export class GridComposer extends Component { } get composerProps(): PropsOf { - const { width, height } = this.env.model.getters.getSheetViewDimensionWithHeaders(); + const { width, height } = this.model().getters.getSheetViewDimensionWithHeaders(); // Remove the wrapper border width const maxHeight = this.props.gridDims.height - this.rect.y - 2 * COMPOSER_BORDER_WIDTH; return { @@ -133,9 +132,9 @@ export class GridComposer extends Component { return `z-index: -1000; opacity: 0;`; // opacity 0 for safari on ios } const _isFormula = isFormula(this.composerStore.currentContent); - const cell = this.env.model.getters.getActiveCell(); - const position = this.env.model.getters.getActivePosition(); - const style = this.env.model.getters.getCellComputedStyle(position); + const cell = this.model().getters.getActiveCell(); + const position = this.model().getters.getActivePosition(); + const style = this.model().getters.getCellComputedStyle(position); // position style const { x: left, y: top, width, height } = this.rect; @@ -210,9 +209,9 @@ export class GridComposer extends Component { } if (shouldRecomputeRect) { - const position = this.env.model.getters.getActivePosition(); - const zone = this.env.model.getters.expandZone(position.sheetId, positionToZone(position)); - this.rect = this.env.model.getters.getVisibleRect(zone); + const position = this.model().getters.getActivePosition(); + const zone = this.model().getters.expandZone(position.sheetId, positionToZone(position)); + this.rect = this.model().getters.getVisibleRect(zone); } } @@ -224,9 +223,9 @@ export class GridComposer extends Component { if (this.isCellReferenceVisible) { return; } - const sheetId = this.env.model.getters.getActiveSheetId(); - const zone = positionToZone(this.env.model.getters.getSelection().anchor.cell); - const rect = this.env.model.getters.getVisibleRect(zone); + const sheetId = this.model().getters.getActiveSheetId(); + const zone = positionToZone(this.model().getters.getSelection().anchor.cell); + const rect = this.model().getters.getVisibleRect(zone); if (!deepEquals(rect, this.rect) || sheetId !== this.composerStore.currentEditedCell.sheetId) { this.isCellReferenceVisible = true; } diff --git a/src/components/composer/top_bar_composer/top_bar_composer.ts b/src/components/composer/top_bar_composer/top_bar_composer.ts index d919e4c1bd..fe88fa4aa3 100644 --- a/src/components/composer/top_bar_composer/top_bar_composer.ts +++ b/src/components/composer/top_bar_composer/top_bar_composer.ts @@ -1,21 +1,22 @@ import { DESKTOP_TOPBAR_TOOLBAR_HEIGHT } from "../../../constants"; +import { Component } from "../../../owl3_compatibility_layer"; import { useStore } from "../../../store_engine/store_hooks"; import { CSSProperties, ComposerFocusType } from "../../../types/misc"; import { SpreadsheetChildEnv } from "../../../types/spreadsheet_env"; import { Store } from "../../../types/store_engine"; import { cssPropertiesToCss } from "../../helpers/css"; +import { useModel } from "../../owl_plugins/model_plugin"; import { ComposerSelection } from "../composer/abstract_composer_store"; import { CellComposerStore } from "../composer/cell_composer_store"; import { Composer } from "../composer/composer"; import { ComposerFocusStore, ComposerInterface } from "../composer_focus_store"; - -import { Component } from "../../../owl3_compatibility_layer"; const COMPOSER_MAX_HEIGHT = 300; export class TopBarComposer extends Component { static template = "o-spreadsheet-TopBarComposer"; static components = { Composer }; + private model = useModel(); private composerFocusStore!: Store; private composerStore!: Store; private composerInterface!: ComposerInterface; @@ -55,7 +56,7 @@ export class TopBarComposer extends Component { "max-height": `${COMPOSER_MAX_HEIGHT}px`, "line-height": "24px", }; - if (this.env.model.getters.isCurrentSheetLocked()) { + if (this.model().getters.isCurrentSheetLocked()) { style["pointer-events"] = "none"; } style.height = this.focus === "inactive" ? `${DESKTOP_TOPBAR_TOOLBAR_HEIGHT}px` : "fit-content"; diff --git a/src/components/composer/top_bar_composer/top_bar_composer.xml b/src/components/composer/top_bar_composer/top_bar_composer.xml index 03c4c5a0f4..0dbfa32aa2 100644 --- a/src/components/composer/top_bar_composer/top_bar_composer.xml +++ b/src/components/composer/top_bar_composer/top_bar_composer.xml @@ -4,7 +4,7 @@
{ static template = "o-spreadsheet-ClickableCellSortIcon"; @@ -21,12 +21,14 @@ export class ClickableCellSortIcon extends Component { }); private hoveredTableStore!: Store; + private model = useModel(); + setup(): void { this.hoveredTableStore = useStore(HoveredTableStore); } get style() { - const cellStyle = this.env.model.getters.getCellComputedStyle(this.props.position); + const cellStyle = this.model().getters.getCellComputedStyle(this.props.position); const size = computeTextFontSizeInPixels(cellStyle); return cssPropertiesToCss({ height: `${size}px`, @@ -37,7 +39,7 @@ export class ClickableCellSortIcon extends Component { } get verticalJustifyClass() { - const cellStyle = this.env.model.getters.getCellComputedStyle(this.props.position); + const cellStyle = this.model().getters.getCellComputedStyle(this.props.position); switch (cellStyle.verticalAlign) { case "top": return "justify-content-start"; diff --git a/src/components/dashboard/clickable_cell_store.ts b/src/components/dashboard/clickable_cell_store.ts index aa900b9d38..f6b3ee0e1d 100644 --- a/src/components/dashboard/clickable_cell_store.ts +++ b/src/components/dashboard/clickable_cell_store.ts @@ -1,6 +1,7 @@ import { markRaw } from "@odoo/owl"; import { toXC } from "../../helpers/coordinates"; import { positionToZone } from "../../helpers/zones"; +import { Model } from "../../model"; import { ComponentConstructor } from "../../owl3_compatibility_layer"; import { CellClickableItem, clickableCellRegistry } from "../../registries/cell_clickable_registry"; import { SpreadsheetStore } from "../../stores/spreadsheet_store"; @@ -13,7 +14,12 @@ export interface ClickableCell { coordinates: Rect; position: CellPosition; title: string; - action: (position: CellPosition, env: SpreadsheetChildEnv, isMiddleClick?: boolean) => void; + action: ( + position: CellPosition, + model: Model, + env: SpreadsheetChildEnv, + isMiddleClick?: boolean + ) => void; component: ComponentConstructor | undefined; componentProps: Record; } diff --git a/src/components/dashboard/dashboard.ts b/src/components/dashboard/dashboard.ts index 45b0a8decb..b688ea98ea 100644 --- a/src/components/dashboard/dashboard.ts +++ b/src/components/dashboard/dashboard.ts @@ -15,6 +15,7 @@ import { useGridDrawing } from "../helpers/draw_grid_hook"; import { useTouchHandlers } from "../helpers/touch_handlers_hook"; import { useWheelHandler } from "../helpers/wheel_hook"; import { getZoomedRect } from "../helpers/zoom"; +import { useModel } from "../owl_plugins/model_plugin"; import { CellPopoverStore } from "../popover/cell_popover_store"; import { Popover } from "../popover/popover"; import { types } from "../props_validation"; @@ -46,6 +47,8 @@ export class SpreadsheetDashboard extends Component { private gridRef = signal(null); private canvasRef = signal(null); + private model = useModel(); + setup() { this.hoveredCell = useStore(DelayedHoveredCellStore); this.clickableCellsStore = useStore(ClickableCellsStore); @@ -54,15 +57,15 @@ export class SpreadsheetDashboard extends Component { const rendererStore = useLocalStore(RendererStore, layers); useChildSubEnv({ getPopoverContainerRect: () => - getZoomedRect(this.env.model.getters.getViewportZoomLevel(), this.getGridRect()), + getZoomedRect(this.model().getters.getViewportZoomLevel(), this.getGridRect()), }); useGridDrawing({ canvasRef: this.canvasRef, rendererStore, renderingCtx: () => ({ dpr: window.devicePixelRatio || 1, - viewports: this.env.model.getters.getViewportCollection(), - ...this.env.model.getters.getSelectionState(), + viewports: this.model().getters.getViewportCollection(), + ...this.model().getters.getSelectionState(), hideGridLines: true, }), }); @@ -75,16 +78,16 @@ export class SpreadsheetDashboard extends Component { useTouchHandlers(this.gridRef, { updateScroll: this.moveCanvas.bind(this), canMoveUp: () => { - const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo(); + const { scrollY } = this.model().getters.getActiveSheetScrollInfo(); return scrollY > 0; }, canMoveDown: () => { - const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset(); - const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo(); + const { maxOffsetY } = this.model().getters.getMaximumSheetOffset(); + const { scrollY } = this.model().getters.getActiveSheetScrollInfo(); return scrollY < maxOffsetY; }, - getZoom: () => this.env.model.getters.getViewportZoomLevel(), - setZoom: (zoom: number) => this.env.model.dispatch("SET_ZOOM", { zoom }), + getZoom: () => this.model().getters.getViewportZoomLevel(), + setZoom: (zoom: number) => this.model().dispatch("SET_ZOOM", { zoom }), }); } @@ -121,7 +124,7 @@ export class SpreadsheetDashboard extends Component { selectClickableCell(ev: MouseEvent, clickableCell: ClickableCell) { const { position, action } = clickableCell; - action(position, this.env, isMiddleClickOrCtrlClick(ev)); + action(position, this.model(), this.env, isMiddleClickOrCtrlClick(ev)); } onClosePopover() { @@ -131,7 +134,7 @@ export class SpreadsheetDashboard extends Component { onGridResized() { const { height, width } = this.props.getGridSize(); const maxWidth = this.getMaxSheetWidth(); - this.env.model.dispatch("RESIZE_SHEETVIEW", { + this.model().dispatch("RESIZE_SHEETVIEW", { width: Math.min(maxWidth, width), height, gridOffsetX: 0, @@ -140,8 +143,8 @@ export class SpreadsheetDashboard extends Component { } private moveCanvas(deltaX: Pixel, deltaY: Pixel) { - const { scrollX, scrollY } = this.env.model.getters.getActiveSheetScrollInfo(); - this.env.model.dispatch("SET_VIEWPORT_OFFSET", { + const { scrollX, scrollY } = this.model().getters.getActiveSheetScrollInfo(); + this.model().dispatch("SET_VIEWPORT_OFFSET", { offsetX: scrollX + deltaX, offsetY: scrollY + deltaY, }); @@ -150,18 +153,18 @@ export class SpreadsheetDashboard extends Component { private getGridRect(): Rect { return { ...getElBoundingRect(this.gridRef()), - ...this.env.model.getters.getSheetViewDimensionWithHeaders(), + ...this.model().getters.getSheetViewDimensionWithHeaders(), }; } private getMaxSheetWidth(): Pixel { - const sheetId = this.env.model.getters.getActiveSheetId(); - const { right } = this.env.model.getters.getSheetZone(sheetId); - return this.env.model.getters.getColDimensions(sheetId, right).end; + const sheetId = this.model().getters.getActiveSheetId(); + const { right } = this.model().getters.getSheetZone(sheetId); + return this.model().getters.getColDimensions(sheetId, right).end; } get dashboardStyle() { - const zoomLevel = this.env.model.getters.getViewportZoomLevel(); + const zoomLevel = this.model().getters.getViewportZoomLevel(); return cssPropertiesToCss({ zoom: `${zoomLevel}` }); } } diff --git a/src/components/error_tooltip/error_tooltip.ts b/src/components/error_tooltip/error_tooltip.ts index 7c805a63df..34bf14cc9b 100644 --- a/src/components/error_tooltip/error_tooltip.ts +++ b/src/components/error_tooltip/error_tooltip.ts @@ -8,6 +8,7 @@ import { SpreadsheetChildEnv } from "../../types/spreadsheet_env"; import { props } from "@odoo/owl"; import { Component } from "../../owl3_compatibility_layer"; +import { useModel } from "../owl_plugins/model_plugin"; import { types } from "../props_validation"; const ERROR_TOOLTIP_MAX_HEIGHT = 80; @@ -20,12 +21,14 @@ export class ErrorToolTip extends Component { "onClosed?": types.function([]), }); + private model = useModel(); + get dataValidationErrorMessage() { - return this.env.model.getters.getInvalidDataValidationMessage(this.props.cellPosition); + return this.model().getters.getInvalidDataValidationMessage(this.props.cellPosition); } get evaluationError() { - const cell = this.env.model.getters.getEvaluatedCell(this.props.cellPosition); + const cell = this.model().getters.getEvaluatedCell(this.props.cellPosition); if (cell.message) { return cell; } @@ -33,7 +36,7 @@ export class ErrorToolTip extends Component { } get errorOriginPositionString() { - if (this.env.model.getters.isDashboard()) { + if (this.model().getters.isDashboard()) { return ""; } const evaluationError = this.evaluationError; @@ -42,9 +45,9 @@ export class ErrorToolTip extends Component { return ""; } const sheetId = position.sheetId; - return this.env.model.getters.getRangeString( - this.env.model.getters.getRangeFromZone(sheetId, positionToZone(position)), - this.env.model.getters.getActiveSheetId() + return this.model().getters.getRangeString( + this.model().getters.getRangeFromZone(sheetId, positionToZone(position)), + this.model().getters.getActiveSheetId() ); } @@ -53,14 +56,14 @@ export class ErrorToolTip extends Component { if (!position) { return; } - const activeSheetId = this.env.model.getters.getActiveSheetId(); + const activeSheetId = this.model().getters.getActiveSheetId(); if (position.sheetId !== activeSheetId) { - this.env.model.dispatch("ACTIVATE_SHEET", { + this.model().dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: position.sheetId, }); } - this.env.model.selection.selectCell(position.col, position.row); + this.model().selection.selectCell(position.col, position.row); } get isSpillErrorBecauseOfMissingHeaders() { @@ -68,7 +71,7 @@ export class ErrorToolTip extends Component { return ( evaluationError?.value === CellErrorType.SpilledBlocked && !evaluationError.errorOriginPosition && - !this.env.model.getters.getSpreadZone(this.props.cellPosition, { ignoreSpillError: true }) + !this.model().getters.getSpreadZone(this.props.cellPosition, { ignoreSpillError: true }) ); } @@ -76,36 +79,32 @@ export class ErrorToolTip extends Component { if (!this.isSpillErrorBecauseOfMissingHeaders) { return; } - const cell = this.env.model.getters.getCell(this.props.cellPosition); + const cell = this.model().getters.getCell(this.props.cellPosition); if (!cell || !cell.isFormula) { return; } - const formula = cell.compiledFormula.toFormulaString(this.env.model.getters); - return getMissingHeadersForSpreadResult( - this.env.model.getters, - this.props.cellPosition, - formula - ); + const formula = cell.compiledFormula.toFormulaString(this.model().getters); + return getMissingHeadersForSpreadResult(this.model().getters, this.props.cellPosition, formula); } addMissingHeaders({ missingCols, missingRows }: { missingCols: number; missingRows: number }) { const sheetId = this.props.cellPosition.sheetId; if (missingCols > 0) { - this.env.model.dispatch("ADD_COLUMNS_ROWS", { + this.model().dispatch("ADD_COLUMNS_ROWS", { sheetId, - sheetName: this.env.model.getters.getSheetName(sheetId), + sheetName: this.model().getters.getSheetName(sheetId), dimension: "COL", - base: this.env.model.getters.getNumberCols(sheetId) - 1, + base: this.model().getters.getNumberCols(sheetId) - 1, position: "after", quantity: missingCols + 20, }); } if (missingRows > 0) { - this.env.model.dispatch("ADD_COLUMNS_ROWS", { + this.model().dispatch("ADD_COLUMNS_ROWS", { sheetId, - sheetName: this.env.model.getters.getSheetName(sheetId), + sheetName: this.model().getters.getSheetName(sheetId), dimension: "ROW", - base: this.env.model.getters.getNumberRows(sheetId) - 1, + base: this.model().getters.getNumberRows(sheetId) - 1, position: "after", quantity: missingRows + 50, }); diff --git a/src/components/figures/chart/chartJs/chartjs.ts b/src/components/figures/chart/chartJs/chartjs.ts index 3a4216cb88..26b6f6dfc4 100644 --- a/src/components/figures/chart/chartJs/chartjs.ts +++ b/src/components/figures/chart/chartJs/chartjs.ts @@ -10,6 +10,7 @@ import { useStore } from "../../../../store_engine/store_hooks"; import { ChartJSRuntime } from "../../../../types/chart/chart"; import { SpreadsheetChildEnv } from "../../../../types/spreadsheet_env"; import { Store } from "../../../../types/store_engine"; +import { useModel } from "../../../owl_plugins/model_plugin"; import { ChartAnimationStore } from "./chartjs_animation_store"; import { chartBackgroundPlugin } from "./chartjs_background_plugin"; import { getCalendarChartController } from "./chartjs_calendar_chart"; @@ -84,6 +85,7 @@ export class ChartJsComponent extends Component { "isFullScreen?": types.boolean(), }); + protected model = useModel(); protected canvas = signal(null); protected chart?: Chart; protected currentRuntime!: ChartJSRuntime; @@ -92,7 +94,7 @@ export class ChartJsComponent extends Component { private currentDevicePixelRatio = window.devicePixelRatio; get chartRuntime(): ChartJSRuntime { - const runtime = this.env.model.getters.getChartRuntime(this.props.chartId); + const runtime = this.model().getters.getChartRuntime(this.props.chartId); if (!("chartJsConfig" in runtime)) { throw new Error("Unsupported chart runtime"); } @@ -133,7 +135,7 @@ export class ChartJsComponent extends Component { } private get shouldAnimate(): boolean { - return this.env.model.getters.isDashboard(); + return this.model().getters.isDashboard(); } protected createChart(chartRuntime: ChartJSRuntime) { @@ -142,7 +144,7 @@ export class ChartJsComponent extends Component { } let chartData = chartRuntime.chartJsConfig as ChartConfiguration; if (this.shouldAnimate && this.animationStore) { - const chartType = this.env.model.getters.getChartDefinition(this.props.chartId)?.type; + const chartType = this.model().getters.getChartDefinition(this.props.chartId)?.type; if (chartType && this.animationStore.animationPlayed[this.animationChartId] !== chartType) { chartData = this.enableAnimationInChartData(chartData); this.animationStore.disableAnimationForChart(this.animationChartId, chartType); @@ -160,7 +162,7 @@ export class ChartJsComponent extends Component { protected updateChartJs(chartRuntime: ChartJSRuntime) { let chartData = chartRuntime.chartJsConfig as ChartConfiguration; if (this.shouldAnimate) { - const chartType = this.env.model.getters.getChartDefinition(this.props.chartId)?.type; + const chartType = this.model().getters.getChartDefinition(this.props.chartId)?.type; if (chartType && this.hasChartDataChanged() && this.animationStore) { chartData = this.enableAnimationInChartData(chartData); this.animationStore.disableAnimationForChart(this.animationChartId, chartType); diff --git a/src/components/figures/chart/chartJs/zoomable_chart/zoomable_chartjs.ts b/src/components/figures/chart/chartJs/zoomable_chart/zoomable_chartjs.ts index b7ea29be68..044b2765c6 100644 --- a/src/components/figures/chart/chartJs/zoomable_chart/zoomable_chartjs.ts +++ b/src/components/figures/chart/chartJs/zoomable_chart/zoomable_chartjs.ts @@ -47,7 +47,7 @@ export class ZoomableChartJsComponent extends ChartJsComponent { } get masterChartContainerStyle() { - const runtime = this.env.model.getters.getChartRuntime(this.props.chartId) as ChartJSRuntime; + const runtime = this.model().getters.getChartRuntime(this.props.chartId) as ChartJSRuntime; if (runtime && !runtime.chartJsConfig.data.datasets.some((ds) => ds.data.length > 1)) { return "opacity: 0.3;"; } @@ -58,7 +58,7 @@ export class ZoomableChartJsComponent extends ChartJsComponent { if (this.props.isFullScreen) { return true; } - const definition = this.env.model.getters.getChartDefinition(this.props.chartId); + const definition = this.model().getters.getChartDefinition(this.props.chartId); return ("zoomable" in definition && definition.zoomable) ?? false; } @@ -369,7 +369,11 @@ export class ZoomableChartJsComponent extends ChartJsComponent { onMasterChartPointerDown(ev: PointerEvent) { this.removeEventListeners(); - const zoomedEvent = withZoom(this.env, ev, this.masterChartCanvas()?.getBoundingClientRect()); + const zoomedEvent = withZoom( + this.model(), + ev, + this.masterChartCanvas()?.getBoundingClientRect() + ); const position = zoomedEvent.offsetX; if (!this.masterChart?.chartArea || !this.chart?.scales?.x) { return; @@ -440,7 +444,11 @@ export class ZoomableChartJsComponent extends ChartJsComponent { }; const onMasterChartDrag = (ev: PointerEvent) => { - const zoomedEvent = withZoom(this.env, ev, this.masterChartCanvas()?.getBoundingClientRect()); + const zoomedEvent = withZoom( + this.model(), + ev, + this.masterChartCanvas()?.getBoundingClientRect() + ); const position = zoomedEvent.offsetX; if (Math.abs(position - startingEventPosition) < 5) { return; @@ -478,7 +486,7 @@ export class ZoomableChartJsComponent extends ChartJsComponent { updateMasterChartCursor(ev: PointerEvent) { const target = ev.target; const { offsetX: x, offsetY: y } = withZoom( - this.env, + this.model(), ev, (target as HTMLElement)?.getBoundingClientRect() ); @@ -515,7 +523,11 @@ export class ZoomableChartJsComponent extends ChartJsComponent { onMasterChartDoubleClick(ev: PointerEvent) { this.mode = undefined; - const zoomedEvent = withZoom(this.env, ev, this.masterChartCanvas()?.getBoundingClientRect()); + const zoomedEvent = withZoom( + this.model(), + ev, + this.masterChartCanvas()?.getBoundingClientRect() + ); const position = zoomedEvent.offsetX; if (!this.masterChart?.chartArea || !this.chart?.scales.x) { return; diff --git a/src/components/figures/chart/chart_dashboard_menu/chart_dashboard_menu.ts b/src/components/figures/chart/chart_dashboard_menu/chart_dashboard_menu.ts index 72564af17f..c9489158d5 100644 --- a/src/components/figures/chart/chart_dashboard_menu/chart_dashboard_menu.ts +++ b/src/components/figures/chart/chart_dashboard_menu/chart_dashboard_menu.ts @@ -11,6 +11,7 @@ import { Store } from "../../../../types/store_engine"; import { FullScreenFigureStore } from "../../../full_screen_figure/full_screen_figure_store"; import { getBoundingRectAsPOJO } from "../../../helpers/dom_helpers"; import { MenuPopover, MenuState } from "../../../menu_popover/menu_popover"; +import { useModel } from "../../../owl_plugins/model_plugin"; import { types } from "../../../props_validation"; import { Select } from "../../../select/select"; @@ -38,6 +39,7 @@ export class ChartDashboardMenu extends Component { private fullScreenFigureStore!: Store; + private model = useModel(); private menuState: MenuState = proxy({ isOpen: false, anchorRect: null, menuItems: [] }); setup() { super.setup(); @@ -49,25 +51,25 @@ export class ChartDashboardMenu extends Component { } get backgroundColor() { - const color = this.env.model.getters.getChartDefinition(this.props.chartId).background; + const color = this.model().getters.getChartDefinition(this.props.chartId).background; return ( - "background-color: " + (color || this.env.model.getters.getSpreadsheetTheme().backgroundColor) + "background-color: " + (color || this.model().getters.getSpreadsheetTheme().backgroundColor) ); } openContextMenu(ev: MouseEvent) { this.menuState.isOpen = true; this.menuState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget as HTMLElement); - const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId); - this.menuState.menuItems = getChartMenuActions(figureId, this.env); + const figureId = this.model().getters.getFigureIdFromChartId(this.props.chartId); + this.menuState.menuItems = getChartMenuActions(figureId, this.model()); } get fullScreenMenuItem(): MenuItem | undefined { if (!this.props.hasFullScreenButton) { return undefined; } - const definition = this.env.model.getters.getChartDefinition(this.props.chartId); - const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId); + const definition = this.model().getters.getChartDefinition(this.props.chartId); + const figureId = this.model().getters.getFigureIdFromChartId(this.props.chartId); if (definition.type === "scorecard") { return undefined; } @@ -83,23 +85,23 @@ export class ChartDashboardMenu extends Component { } get regionOptions(): ValueAndLabel[] { - return this.env.model.getters - .getAvailableChartRegions(this.props.chartId) + return this.model() + .getters.getAvailableChartRegions(this.props.chartId) .map((r) => ({ value: r.id, label: r.label })); } get selectedRegion(): string { - const definition = this.env.model.getters.getChartDefinition(this.props.chartId); + const definition = this.model().getters.getChartDefinition(this.props.chartId); if (!definition.type.includes("geo")) { return ""; } const geoDef = definition as GeoChartDefinition; - const availableRegions = this.env.model.getters.getGeoChartAvailableRegions(); + const availableRegions = this.model().getters.getGeoChartAvailableRegions(); return geoDef.region || availableRegions[0]?.id || ""; } onRegionSelected(region: string) { - this.env.model.dispatch("UPDATE_CHART_REGION", { + this.model().dispatch("UPDATE_CHART_REGION", { chartId: this.props.chartId, region, }); diff --git a/src/components/figures/chart/gauge/gauge_chart_component.ts b/src/components/figures/chart/gauge/gauge_chart_component.ts index 113d2dc3f6..bd36ef57a1 100644 --- a/src/components/figures/chart/gauge/gauge_chart_component.ts +++ b/src/components/figures/chart/gauge/gauge_chart_component.ts @@ -7,6 +7,7 @@ import { useStore } from "../../../../store_engine/store_hooks"; import { GaugeChartRuntime } from "../../../../types/chart/gauge_chart"; import { SpreadsheetChildEnv } from "../../../../types/spreadsheet_env"; import { Store } from "../../../../types/store_engine"; +import { useModel } from "../../../owl_plugins/model_plugin"; import { ChartAnimationStore } from "../chartJs/chartjs_animation_store"; const ANIMATION_DURATION = 1000; @@ -23,12 +24,14 @@ export class GaugeChartComponent extends Component { private animationStore: Store | undefined; + private model = useModel(); + get runtime(): GaugeChartRuntime { - return this.env.model.getters.getChartRuntime(this.props.chartId) as GaugeChartRuntime; + return this.model().getters.getChartRuntime(this.props.chartId) as GaugeChartRuntime; } setup() { - if (this.env.model.getters.isDashboard()) { + if (this.model().getters.isDashboard()) { this.animationStore = useStore(ChartAnimationStore); } @@ -37,21 +40,21 @@ export class GaugeChartComponent extends Component { useLayoutEffect( () => { if ( - this.env.model.getters.isDashboard() && + this.model().getters.isDashboard() && lastRuntime === undefined && // first render this.animationStore?.animationPlayed[this.animationChartId] !== "gauge" ) { animation = this.drawGaugeWithAnimation(); this.animationStore?.disableAnimationForChart(this.animationChartId, "gauge"); } else if ( - this.env.model.getters.isDashboard() && + this.model().getters.isDashboard() && lastRuntime !== undefined && // not first render !deepEquals(this.runtime, lastRuntime) ) { animation = this.drawGaugeWithAnimation(); this.animationStore?.disableAnimationForChart(this.animationChartId, "gauge"); } else { - const zoom = this.env.model.getters.getViewportZoomLevel(); + const zoom = this.model().getters.getViewportZoomLevel(); drawGaugeChart(this.canvasEl, this.runtime, zoom); } @@ -72,7 +75,7 @@ export class GaugeChartComponent extends Component { animation.stop(); animation = null; } - drawGaugeChart(this.canvasEl, this.runtime, this.env.model.getters.getViewportZoomLevel()); + drawGaugeChart(this.canvasEl, this.runtime, this.model().getters.getViewportZoomLevel()); }); onMounted(() => { const canvas = this.canvas(); diff --git a/src/components/figures/chart/scorecard/chart_scorecard.ts b/src/components/figures/chart/scorecard/chart_scorecard.ts index 749e09d19e..ffdc966354 100644 --- a/src/components/figures/chart/scorecard/chart_scorecard.ts +++ b/src/components/figures/chart/scorecard/chart_scorecard.ts @@ -5,6 +5,7 @@ import { Component, useLayoutEffect } from "../../../../owl3_compatibility_layer import { ScorecardChartRuntime } from "../../../../types/chart/scorecard_chart"; import { SpreadsheetChildEnv } from "../../../../types/spreadsheet_env"; import { getZoomedRect } from "../../../helpers/zoom"; +import { useModel } from "../../../owl_plugins/model_plugin"; export class ScorecardChart extends Component { static template = "o-spreadsheet-ScorecardChart"; @@ -15,13 +16,15 @@ export class ScorecardChart extends Component { }); private canvas = signal(null); + private model = useModel(); + get runtime(): ScorecardChartRuntime { - return this.env.model.getters.getChartRuntime(this.props.chartId) as ScorecardChartRuntime; + return this.model().getters.getChartRuntime(this.props.chartId) as ScorecardChartRuntime; } get title(): string { - const title = this.env.model.getters.getChartDefinition(this.props.chartId).title.text; - return title ? this.env.model.getters.dynamicTranslate(title) : ""; + const title = this.model().getters.getChartDefinition(this.props.chartId).title.text; + return title ? this.model().getters.dynamicTranslate(title) : ""; } setup() { @@ -48,7 +51,7 @@ export class ScorecardChart extends Component { if (!canvas) { return; } - const zoom = this.env.model.getters.getViewportZoomLevel(); + const zoom = this.model().getters.getViewportZoomLevel(); const config = getScorecardConfiguration( getZoomedRect(1 / zoom, canvas.getBoundingClientRect()), this.runtime diff --git a/src/components/figures/figure/figure.ts b/src/components/figures/figure/figure.ts index 935c1f27e9..bcdd7ee7c2 100644 --- a/src/components/figures/figure/figure.ts +++ b/src/components/figures/figure/figure.ts @@ -14,6 +14,7 @@ import { } from "../../helpers/dom_helpers"; import { withZoom } from "../../helpers/zoom"; import { MenuPopover, MenuState } from "../../menu_popover/menu_popover"; +import { useModel } from "../../owl_plugins/model_plugin"; import { types } from "../../props_validation"; type ResizeAnchor = @@ -59,10 +60,11 @@ export class FigureComponent extends Component { private figureWrapperRef = signal(null); private menuButtonRef = signal(null); + private model = useModel(); private borderWidth!: number; get isSelected(): boolean { - return this.env.model.getters.getSelectedFigureIds().includes(this.props.figureUI.id); + return this.model().getters.getSelectedFigureIds().includes(this.props.figureUI.id); } get figureRegistry() { @@ -70,7 +72,7 @@ export class FigureComponent extends Component { } private getBorderWidth(): Pixel { - if (this.env.model.getters.isDashboard()) { + if (this.model().getters.isDashboard()) { return 0; } return this.isSelected ? ACTIVE_BORDER_WIDTH : this.borderWidth; @@ -115,7 +117,7 @@ export class FigureComponent extends Component { const borderWidth = figureRegistry.get(this.props.figureUI.tag).borderWidth; this.borderWidth = borderWidth !== undefined ? borderWidth : BORDER_WIDTH; useLayoutEffect(() => { - const selectedFigureIds = this.env.model.getters.getSelectedFigureIds(); + const selectedFigureIds = this.model().getters.getSelectedFigureIds(); const thisFigureId = this.props.figureUI.id; const el = this.figureRef(); if (selectedFigureIds.includes(thisFigureId)) { @@ -153,9 +155,9 @@ export class FigureComponent extends Component { switch (keyDownShortcut) { case "Delete": case "Backspace": - this.env.model.dispatch("DELETE_FIGURES", { - sheetId: this.env.model.getters.getActiveSheetId(), - figureIds: this.env.model.getters.getSelectedFigureIds(), + this.model().dispatch("DELETE_FIGURES", { + sheetId: this.model().getters.getActiveSheetId(), + figureIds: this.model().getters.getSelectedFigureIds(), }); ev.preventDefault(); ev.stopPropagation(); @@ -168,11 +170,11 @@ export class FigureComponent extends Component { case "ArrowLeft": case "ArrowRight": case "ArrowUp": - const sheetId = this.env.model.getters.getActiveSheetId(); - const figureIds = this.env.model.getters.getSelectedFigureIds(); + const sheetId = this.model().getters.getActiveSheetId(); + const figureIds = this.model().getters.getSelectedFigureIds(); const figures: MoveFiguresPayload[] = []; for (const figureId of figureIds) { - const figure = this.env.model.getters.getFigure(sheetId, figureId); + const figure = this.model().getters.getFigure(sheetId, figureId); if (!figure) { continue; } @@ -180,13 +182,13 @@ export class FigureComponent extends Component { sheetId, figureId, ...this.postionInBoundary( - this.env.model.getters.getFigureUI(sheetId, figure), + this.model().getters.getFigureUI(sheetId, figure), ev.key, ev.shiftKey ), }); } - this.env.model.dispatch("MOVE_FIGURES", { figures }); + this.model().dispatch("MOVE_FIGURES", { figures }); ev.preventDefault(); ev.stopPropagation(); break; @@ -198,9 +200,9 @@ export class FigureComponent extends Component { case "Ctrl+Y": case "Ctrl+Z": if (keyDownShortcut === "Ctrl+Y") { - this.env.model.dispatch("REQUEST_REDO"); + this.model().dispatch("REQUEST_REDO"); } else if (keyDownShortcut === "Ctrl+Z") { - this.env.model.dispatch("REQUEST_UNDO"); + this.model().dispatch("REQUEST_UNDO"); } ev.preventDefault(); ev.stopPropagation(); @@ -209,7 +211,7 @@ export class FigureComponent extends Component { } private postionInBoundary(position: AnchorOffset, key: string, shift: boolean): AnchorOffset { - const sheetId = this.env.model.getters.getActiveSheetId(); + const sheetId = this.model().getters.getActiveSheetId(); const shiftAmount = shift ? 1 : 5; let { col, row, offset } = position; offset = { ...offset }; @@ -217,7 +219,7 @@ export class FigureComponent extends Component { case "ArrowUp": if (offset.y < shiftAmount) { row--; - offset.y = this.env.model.getters.getRowSize(sheetId, row) - shiftAmount + offset.y; + offset.y = this.model().getters.getRowSize(sheetId, row) - shiftAmount + offset.y; } else { offset.y -= shiftAmount; } @@ -225,13 +227,13 @@ export class FigureComponent extends Component { case "ArrowLeft": if (offset.x < shiftAmount) { col--; - offset.x = this.env.model.getters.getColSize(sheetId, col) - shiftAmount + offset.x; + offset.x = this.model().getters.getColSize(sheetId, col) - shiftAmount + offset.x; } else { offset.x -= shiftAmount; } break; case "ArrowDown": - const rowSize = this.env.model.getters.getRowSize(sheetId, row); + const rowSize = this.model().getters.getRowSize(sheetId, row); if (offset.y + shiftAmount >= rowSize) { row++; offset.y = offset.y + shiftAmount - rowSize; @@ -240,7 +242,7 @@ export class FigureComponent extends Component { } break; case "ArrowRight": - const colSize = this.env.model.getters.getColSize(sheetId, col); + const colSize = this.model().getters.getColSize(sheetId, col); if (offset.x + shiftAmount >= colSize) { col++; offset.x = offset.x + shiftAmount - colSize; @@ -252,10 +254,10 @@ export class FigureComponent extends Component { } onContextMenu(ev: MouseEvent) { - if (this.env.model.getters.isDashboard()) { + if (this.model().getters.isDashboard()) { return; } - const zoomedMouseEvent = withZoom(this.env, ev); + const zoomedMouseEvent = withZoom(this.model(), ev); this.openContextMenu({ x: zoomedMouseEvent.clientX, y: zoomedMouseEvent.clientY, @@ -266,7 +268,7 @@ export class FigureComponent extends Component { showMenu(ev: MouseEvent) { if (!this.isSelected) { - this.env.model.dispatch("SELECT_FIGURE", { + this.model().dispatch("SELECT_FIGURE", { figureId: this.props.figureUI.id, selectMultiple: ev.shiftKey || isCtrlKey(ev), }); @@ -279,7 +281,7 @@ export class FigureComponent extends Component { this.menuState.anchorRect = anchorRect; this.menuState.menuItems = figureRegistry .get(this.props.figureUI.tag) - .menuBuilder(this.props.figureUI.id, this.env); + .menuBuilder(this.props.figureUI.id, this.model()); } editWrapperStyle(properties: CSSProperties) { @@ -295,8 +297,8 @@ export class FigureComponent extends Component { return ( this.isSelected && !this.env.isMobile() && - !this.env.model.getters.isDashboard() && - !this.env.model.getters.isCurrentSheetLocked() + !this.model().getters.isDashboard() && + !this.model().getters.isCurrentSheetLocked() ); } } diff --git a/src/components/figures/figure/figure.xml b/src/components/figures/figure/figure.xml index 7fd298a4b3..3440633370 100644 --- a/src/components/figures/figure/figure.xml +++ b/src/components/figures/figure/figure.xml @@ -10,7 +10,7 @@ t-att-class="this.props.class" t-on-pointerdown.stop="(ev) => this.onMouseDown(ev)" t-on-click="this.onClick" - t-on-contextmenu.prevent.stop="(ev) => !this.env.model.getters.isReadonly() and this.onContextMenu(ev)" + t-on-contextmenu.prevent.stop="(ev) => !this.model().getters.isReadonly() and this.onContextMenu(ev)" t-ref="this.figureRef" t-att-style="this.props.style" t-att-data-id="this.props.figureUI.id" @@ -24,12 +24,10 @@ editFigureStyle.bind="this.editWrapperStyle" openContextMenu.bind="this.openContextMenu" /> -
+
@@ -43,7 +41,7 @@ />