diff --git a/src/registries/menu_items_registry.ts b/src/registries/menu_items_registry.ts index dab3b2eee5..32902591d7 100644 --- a/src/registries/menu_items_registry.ts +++ b/src/registries/menu_items_registry.ts @@ -58,7 +58,7 @@ export interface MenuItem { textColor?: Color; } -type MenuItemsBuilder = (env: SpreadsheetChildEnv) => MenuItemSpec[]; +export type MenuItemsBuilder = (env: SpreadsheetChildEnv) => MenuItemSpec[]; type MenuChildren = (MenuItemSpec | MenuItemsBuilder)[]; export function createMenu(menuItems: MenuItemSpec[]): MenuItem[] { diff --git a/src/registries/menus/cell_menu_registry.ts b/src/registries/menus/cell_menu_registry.ts index e680266e53..df7ddd8e27 100644 --- a/src/registries/menus/cell_menu_registry.ts +++ b/src/registries/menus/cell_menu_registry.ts @@ -1,6 +1,8 @@ import { _lt } from "../../translation"; import { MenuItemRegistry } from "../menu_items_registry"; -import * as ACTIONS from "./menu_items_actions"; + +import * as ACTION_EDIT from "./items/edit_menu_items"; +import * as ACTION_INSERT from "./items/insert_menu_items"; //------------------------------------------------------------------------------ // Context Menu Registry @@ -10,98 +12,78 @@ export const cellMenuRegistry = new MenuItemRegistry(); cellMenuRegistry .add("cut", { - name: _lt("Cut"), - description: "Ctrl+X", + ...ACTION_EDIT.cutMenuItem, sequence: 10, - action: ACTIONS.CUT_ACTION, }) .add("copy", { - name: _lt("Copy"), - description: "Ctrl+C", + ...ACTION_EDIT.copyMenuItem, sequence: 20, - isReadonlyAllowed: true, - action: ACTIONS.COPY_ACTION, }) .add("paste", { - name: _lt("Paste"), - description: "Ctrl+V", + ...ACTION_EDIT.pasteMenuItem, sequence: 30, - action: ACTIONS.PASTE_ACTION, }) .add("paste_special", { - name: _lt("Paste special"), + ...ACTION_EDIT.pasteSpecialMenuItem, sequence: 40, separator: true, - isVisible: ACTIONS.IS_NOT_CUT_OPERATION, }) .addChild("paste_value_only", ["paste_special"], { - name: _lt("Paste values only"), + ...ACTION_EDIT.pasteSpecialValueMenuItem, sequence: 10, - action: ACTIONS.PASTE_VALUE_ACTION, }) .addChild("paste_format_only", ["paste_special"], { - name: _lt("Paste format only"), + ...ACTION_EDIT.pasteSpecialFormatMenuItem, sequence: 20, - action: ACTIONS.PASTE_FORMAT_ACTION, }) .add("add_row_before", { - name: ACTIONS.CELL_INSERT_ROWS_BEFORE_NAME, + ...ACTION_INSERT.cellInsertRowsBeforeMenuItem, sequence: 70, - action: ACTIONS.INSERT_ROWS_BEFORE_ACTION, - isVisible: ACTIONS.IS_ONLY_ONE_RANGE, }) .add("add_column_before", { - name: ACTIONS.CELL_INSERT_COLUMNS_BEFORE_NAME, + ...ACTION_INSERT.cellInsertColsBeforeMenuItem, sequence: 90, - action: ACTIONS.INSERT_COLUMNS_BEFORE_ACTION, - isVisible: ACTIONS.IS_ONLY_ONE_RANGE, }) .add("insert_cell", { - name: _lt("Insert cells"), + ...ACTION_INSERT.insertCellMenuItem, sequence: 100, - isVisible: ACTIONS.IS_ONLY_ONE_RANGE, separator: true, }) .addChild("insert_cell_down", ["insert_cell"], { + ...ACTION_INSERT.insertCellShiftDownMenuItem, name: _lt("Shift down"), sequence: 10, - action: ACTIONS.INSERT_CELL_SHIFT_DOWN, }) .addChild("insert_cell_right", ["insert_cell"], { + ...ACTION_INSERT.insertCellShiftRightMenuItem, name: _lt("Shift right"), sequence: 20, - action: ACTIONS.INSERT_CELL_SHIFT_RIGHT, }) .add("delete_row", { - name: ACTIONS.REMOVE_ROWS_NAME, + ...ACTION_EDIT.deleteRowMenuItem, sequence: 110, - action: ACTIONS.REMOVE_ROWS_ACTION, - isVisible: ACTIONS.IS_ONLY_ONE_RANGE, }) .add("delete_column", { - name: ACTIONS.REMOVE_COLUMNS_NAME, + ...ACTION_EDIT.deleteColMenuItem, sequence: 120, - action: ACTIONS.REMOVE_COLUMNS_ACTION, - isVisible: ACTIONS.IS_ONLY_ONE_RANGE, }) .add("delete_cell", { - name: _lt("Delete cells"), + ...ACTION_EDIT.deleteCellsMenuItem, sequence: 130, - isVisible: ACTIONS.IS_ONLY_ONE_RANGE, }) .addChild("delete_cell_up", ["delete_cell"], { + ...ACTION_EDIT.deleteCellShiftUpMenuItem, name: _lt("Shift up"), sequence: 10, - action: ACTIONS.DELETE_CELL_SHIFT_UP, }) - .addChild("delete_cell_down", ["delete_cell"], { + .addChild("delete_cell_left", ["delete_cell"], { + ...ACTION_EDIT.deleteCellShiftLeftMenuItem, name: _lt("Shift left"), sequence: 20, - action: ACTIONS.DELETE_CELL_SHIFT_LEFT, }) .add("insert_link", { + ...ACTION_INSERT.insertLinkMenuItem, name: _lt("Insert link"), - separator: true, sequence: 150, - action: ACTIONS.INSERT_LINK, + separator: true, }); diff --git a/src/registries/menus/col_menu_registry.ts b/src/registries/menus/col_menu_registry.ts index efa6851c68..978ae07116 100644 --- a/src/registries/menus/col_menu_registry.ts +++ b/src/registries/menus/col_menu_registry.ts @@ -1,112 +1,81 @@ import { _lt } from "../../translation"; -import { SpreadsheetChildEnv } from "../../types"; import { MenuItemRegistry } from "../menu_items_registry"; -import * as ACTIONS from "./menu_items_actions"; +import * as ACTION_DATA from "./items/data_menu_items"; +import * as ACTION_EDIT from "./items/edit_menu_items"; +import * as ACTION_FORMAT from "./items/format_menu_items"; +import * as ACTION_INSERT from "./items/insert_menu_items"; +import * as ACTION_VIEW from "./items/view_menu_items"; export const colMenuRegistry = new MenuItemRegistry(); colMenuRegistry .add("cut", { - name: _lt("Cut"), - description: "Ctrl+X", + ...ACTION_EDIT.cutMenuItem, sequence: 10, - action: ACTIONS.CUT_ACTION, }) .add("copy", { - name: _lt("Copy"), - description: "Ctrl+C", + ...ACTION_EDIT.copyMenuItem, sequence: 20, - isReadonlyAllowed: true, - action: ACTIONS.COPY_ACTION, }) .add("paste", { - name: _lt("Paste"), - description: "Ctrl+V", + ...ACTION_EDIT.pasteMenuItem, sequence: 30, - action: ACTIONS.PASTE_ACTION, }) .add("paste_special", { - name: _lt("Paste special"), + ...ACTION_EDIT.pasteSpecialMenuItem, sequence: 40, separator: true, - isVisible: ACTIONS.IS_NOT_CUT_OPERATION, }) .addChild("paste_value_only", ["paste_special"], { - name: _lt("Paste value only"), + ...ACTION_EDIT.pasteSpecialValueMenuItem, sequence: 10, - action: ACTIONS.PASTE_VALUE_ACTION, }) .addChild("paste_format_only", ["paste_special"], { - name: _lt("Paste format only"), + ...ACTION_EDIT.pasteSpecialFormatMenuItem, sequence: 20, - action: ACTIONS.PASTE_FORMAT_ACTION, }) .add("sort_columns", { + ...ACTION_DATA.sortRangeMenuItem, name: (env) => env.model.getters.getActiveCols().size > 1 ? _lt("Sort columns") : _lt("Sort column"), sequence: 50, - isVisible: ACTIONS.IS_ONLY_ONE_RANGE, separator: true, }) .addChild("sort_ascending", ["sort_columns"], { - name: _lt("Ascending (A ⟶ Z)"), + ...ACTION_DATA.sortAscendingenuItem, sequence: 10, - action: ACTIONS.SORT_CELLS_ASCENDING, }) .addChild("sort_descending", ["sort_columns"], { - name: _lt("Descending (Z ⟶ A)"), + ...ACTION_DATA.sortDescendingMenuItem, sequence: 20, - action: ACTIONS.SORT_CELLS_DESCENDING, }) .add("add_column_before", { - name: ACTIONS.COLUMN_INSERT_COLUMNS_BEFORE_NAME, + ...ACTION_INSERT.colInsertColsBeforeMenuItem, sequence: 70, - action: ACTIONS.INSERT_COLUMNS_BEFORE_ACTION, }) .add("add_column_after", { - name: ACTIONS.COLUMN_INSERT_COLUMNS_AFTER_NAME, + ...ACTION_INSERT.colInsertColsAfterMenuItem, sequence: 80, - action: ACTIONS.INSERT_COLUMNS_AFTER_ACTION, }) .add("delete_column", { - name: ACTIONS.REMOVE_COLUMNS_NAME, + ...ACTION_EDIT.deleteColsMenuItem, sequence: 90, - action: ACTIONS.REMOVE_COLUMNS_ACTION, }) .add("clear_column", { - name: ACTIONS.DELETE_CONTENT_COLUMNS_NAME, + ...ACTION_EDIT.clearColsMenuItem, sequence: 100, - action: ACTIONS.DELETE_CONTENT_COLUMNS_ACTION, }) .add("hide_columns", { - name: ACTIONS.HIDE_COLUMNS_NAME, + ...ACTION_VIEW.hideColsMenuItem, sequence: 85, - action: ACTIONS.HIDE_COLUMNS_ACTION, - isVisible: (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const hiddenCols = env.model.getters.getHiddenColsGroups(sheetId).flat(); - return ( - env.model.getters.getNumberCols(sheetId) > - hiddenCols.length + env.model.getters.getElementsFromSelection("COL").length - ); - }, separator: true, }) .add("unhide_columns", { - name: _lt("Unhide columns"), + ...ACTION_VIEW.unhideColsMenuItem, sequence: 86, - action: ACTIONS.UNHIDE_COLUMNS_ACTION, - isVisible: (env: SpreadsheetChildEnv) => { - const hiddenCols = env.model.getters - .getHiddenColsGroups(env.model.getters.getActiveSheetId()) - .flat(); - const currentCols = env.model.getters.getElementsFromSelection("COL"); - return currentCols.some((col) => hiddenCols.includes(col)); - }, separator: true, }) .add("conditional_formatting", { - name: _lt("Conditional formatting"), + ...ACTION_FORMAT.formatCFMenuItem, sequence: 110, - action: ACTIONS.OPEN_CF_SIDEPANEL_ACTION, }); diff --git a/src/registries/menus/items/data_menu_items.ts b/src/registries/menus/items/data_menu_items.ts new file mode 100644 index 0000000000..0927fd28bb --- /dev/null +++ b/src/registries/menus/items/data_menu_items.ts @@ -0,0 +1,33 @@ +import { _lt } from "../../../translation"; +import { MenuItemSpec } from "../../menu_items_registry"; +import * as ACTIONS from "./../menu_items_actions"; + +export const sortRangeMenuItem: MenuItemSpec = { + name: _lt("Sort range"), + isVisible: ACTIONS.IS_ONLY_ONE_RANGE, +}; + +export const sortAscendingenuItem: MenuItemSpec = { + name: _lt("Ascending (A ⟶ Z)"), + action: ACTIONS.SORT_CELLS_ASCENDING, +}; + +export const sortDescendingMenuItem: MenuItemSpec = { + name: _lt("Descending (Z ⟶ A)"), + action: ACTIONS.SORT_CELLS_DESCENDING, +}; + +export const addDataFilterMenuItem: MenuItemSpec = { + name: _lt("Create filter"), + action: ACTIONS.FILTERS_CREATE_FILTER_TABLE, + isVisible: (env) => !ACTIONS.SELECTION_CONTAINS_FILTER(env), + isEnabled: (env) => ACTIONS.SELECTION_IS_CONTINUOUS(env), + icon: "o-spreadsheet-Icon.FILTER_ICON_INACTIVE", +}; + +export const removeDataFilterMenuItem: MenuItemSpec = { + name: _lt("Remove filter"), + action: ACTIONS.FILTERS_REMOVE_FILTER_TABLE, + isVisible: ACTIONS.SELECTION_CONTAINS_FILTER, + icon: "o-spreadsheet-Icon.FILTER_ICON_INACTIVE", +}; diff --git a/src/registries/menus/items/edit_menu_items.ts b/src/registries/menus/items/edit_menu_items.ts new file mode 100644 index 0000000000..2bbf94541d --- /dev/null +++ b/src/registries/menus/items/edit_menu_items.ts @@ -0,0 +1,108 @@ +import { _lt } from "../../../translation"; +import { MenuItemSpec } from "../../menu_items_registry"; +import * as ACTIONS from "./../menu_items_actions"; + +export const undoMenuItem: MenuItemSpec = { + name: _lt("Undo"), + description: "Ctrl+Z", + action: ACTIONS.UNDO_ACTION, + icon: "o-spreadsheet-Icon.UNDO", +}; + +export const redoMenuItem: MenuItemSpec = { + name: _lt("Redo"), + description: "Ctrl+Y", + action: ACTIONS.REDO_ACTION, + icon: "o-spreadsheet-Icon.REDO", +}; + +export const copyMenuItem: MenuItemSpec = { + name: _lt("Copy"), + description: "Ctrl+C", + isReadonlyAllowed: true, + action: ACTIONS.COPY_ACTION, +}; + +export const cutMenuItem: MenuItemSpec = { + name: _lt("Cut"), + description: "Ctrl+X", + action: ACTIONS.CUT_ACTION, +}; + +export const pasteMenuItem: MenuItemSpec = { + name: _lt("Paste"), + description: "Ctrl+V", + action: ACTIONS.PASTE_ACTION, +}; + +export const pasteSpecialMenuItem: MenuItemSpec = { + name: _lt("Paste special"), + isVisible: ACTIONS.IS_NOT_CUT_OPERATION, +}; + +export const pasteSpecialValueMenuItem: MenuItemSpec = { + name: _lt("Paste value only"), + action: ACTIONS.PASTE_VALUE_ACTION, +}; + +export const pasteSpecialFormatMenuItem: MenuItemSpec = { + name: _lt("Paste format only"), + action: ACTIONS.PASTE_FORMAT_ACTION, +}; + +export const findAndReplaceMenuItem: MenuItemSpec = { + name: _lt("Find and replace"), + description: "Ctrl+H", + isReadonlyAllowed: true, + action: ACTIONS.OPEN_FAR_SIDEPANEL_ACTION, +}; + +export const deleteValuesMenuItem: MenuItemSpec = { + name: _lt("Delete values"), + action: ACTIONS.DELETE_CONTENT_ACTION, +}; + +export const deleteRowsMenuItem: MenuItemSpec = { + name: ACTIONS.REMOVE_ROWS_NAME, + action: ACTIONS.REMOVE_ROWS_ACTION, +}; + +export const deleteRowMenuItem: MenuItemSpec = { + ...deleteRowsMenuItem, + isVisible: ACTIONS.IS_ONLY_ONE_RANGE, +}; + +export const clearRowsMenuItem: MenuItemSpec = { + name: ACTIONS.DELETE_CONTENT_ROWS_NAME, + action: ACTIONS.DELETE_CONTENT_ROWS_ACTION, +}; + +export const deleteColsMenuItem: MenuItemSpec = { + name: ACTIONS.REMOVE_COLUMNS_NAME, + action: ACTIONS.REMOVE_COLUMNS_ACTION, +}; + +export const deleteColMenuItem: MenuItemSpec = { + ...deleteColsMenuItem, + isVisible: ACTIONS.IS_ONLY_ONE_RANGE, +}; + +export const clearColsMenuItem: MenuItemSpec = { + name: ACTIONS.DELETE_CONTENT_COLUMNS_NAME, + action: ACTIONS.DELETE_CONTENT_COLUMNS_ACTION, +}; + +export const deleteCellsMenuItem: MenuItemSpec = { + name: _lt("Delete cells"), + isVisible: ACTIONS.IS_ONLY_ONE_RANGE, +}; + +export const deleteCellShiftUpMenuItem: MenuItemSpec = { + name: _lt("Delete cell and shift up"), + action: ACTIONS.DELETE_CELL_SHIFT_UP, +}; + +export const deleteCellShiftLeftMenuItem: MenuItemSpec = { + name: _lt("Delete cell and shift left"), + action: ACTIONS.DELETE_CELL_SHIFT_LEFT, +}; diff --git a/src/registries/menus/items/format_menu_items.ts b/src/registries/menus/items/format_menu_items.ts new file mode 100644 index 0000000000..47fe14bfef --- /dev/null +++ b/src/registries/menus/items/format_menu_items.ts @@ -0,0 +1,211 @@ +import { NumberFormatTerms } from "../../../components/translations_terms"; +import { DEFAULT_FONT_SIZE, FONT_SIZES } from "../../../constants"; +import { _lt } from "../../../translation"; +import { MenuItemSpec } from "../../menu_items_registry"; +import * as ACTIONS from "./../menu_items_actions"; + +export const formatNumberMenuItem: MenuItemSpec = { + name: _lt("Numbers"), +}; + +export const formatNumberAutomaticMenuItem: MenuItemSpec = { + name: NumberFormatTerms.Automatic, + action: ACTIONS.FORMAT_AUTOMATIC_ACTION, + isActive: (env) => isAutomaticFormatSelected(env), +}; + +export const formatNumberNumberMenuItem: MenuItemSpec = { + name: NumberFormatTerms.Number, + description: "1,000.12", + action: ACTIONS.FORMAT_NUMBER_ACTION, + isActive: (env) => isFormatSelected(env, "#,##0.00"), +}; + +export const formatNumberPercentMenuItem: MenuItemSpec = { + name: NumberFormatTerms.Percent, + description: "10.12%", + action: ACTIONS.FORMAT_PERCENT_ACTION, + isActive: (env) => isFormatSelected(env, "0.00%"), +}; + +export const formatNumberCurrencyMenuItem: MenuItemSpec = { + name: NumberFormatTerms.Currency, + description: "$1,000.12", + action: ACTIONS.FORMAT_CURRENCY_ACTION, + isActive: (env) => isFormatSelected(env, "[$$]#,##0.00"), +}; + +export const formatNumberCurrencyRoundedMenuItem: MenuItemSpec = { + name: NumberFormatTerms.CurrencyRounded, + description: "$1,000", + action: ACTIONS.FORMAT_CURRENCY_ROUNDED_ACTION, + isActive: (env) => isFormatSelected(env, "[$$]#,##0"), +}; + +export const formatCustomCurrencyMenuItem: MenuItemSpec = { + name: NumberFormatTerms.CustomCurrency, + isVisible: (env) => env.loadCurrencies !== undefined, + action: ACTIONS.OPEN_CUSTOM_CURRENCY_SIDEPANEL_ACTION, +}; + +export const formatNumberDateMenuItem: MenuItemSpec = { + name: NumberFormatTerms.Date, + description: "9/26/2008", + action: ACTIONS.FORMAT_DATE_ACTION, + isActive: (env) => isFormatSelected(env, "m/d/yyyy"), +}; + +export const formatNumberTimeMenuItem: MenuItemSpec = { + name: NumberFormatTerms.Time, + description: "10:43:00 PM", + action: ACTIONS.FORMAT_TIME_ACTION, + isActive: (env) => isFormatSelected(env, "hh:mm:ss a"), +}; + +export const formatNumberDateTimeMenuItem: MenuItemSpec = { + name: NumberFormatTerms.DateTime, + description: "9/26/2008 22:43:00", + action: ACTIONS.FORMAT_DATE_TIME_ACTION, + isActive: (env) => isFormatSelected(env, "m/d/yyyy hh:mm:ss"), +}; + +export const formatNumberDurationMenuItem: MenuItemSpec = { + name: NumberFormatTerms.Duration, + description: "27:51:38", + action: ACTIONS.FORMAT_DURATION_ACTION, + isActive: (env) => isFormatSelected(env, "hhhh:mm:ss"), +}; + +export const formatBoldMenuItem: MenuItemSpec = { + name: _lt("Bold"), + description: "Ctrl+B", + action: ACTIONS.FORMAT_BOLD_ACTION, + icon: "o-spreadsheet-Icon.BOLD", +}; + +export const formatItalicMenuItem: MenuItemSpec = { + name: _lt("Italic"), + description: "Ctrl+I", + action: ACTIONS.FORMAT_ITALIC_ACTION, + icon: "o-spreadsheet-Icon.ITALIC", +}; + +export const formatUnderlineMenuItem: MenuItemSpec = { + name: _lt("Underline"), + description: "Ctrl+U", + action: ACTIONS.FORMAT_UNDERLINE_ACTION, + icon: "o-spreadsheet-Icon.UNDERLINE", +}; + +export const formatStrikethroughMenuItem: MenuItemSpec = { + name: _lt("Strikethrough"), + action: ACTIONS.FORMAT_STRIKETHROUGH_ACTION, + icon: "o-spreadsheet-Icon.STRIKE", +}; + +export const formatFontSizeMenuItem: MenuItemSpec = { + name: _lt("Font size"), + children: fontSizeMenuBuilder(), +}; + +export const formatAlignmentMenuItem: MenuItemSpec = { + name: _lt("Alignment"), + icon: "o-spreadsheet-Icon.ALIGN_LEFT", +}; + +export const formatAlignmentLeftMenuItem: MenuItemSpec = { + name: _lt("Left"), + action: (env) => ACTIONS.setStyle(env, { align: "left" }), + icon: "o-spreadsheet-Icon.ALIGN_LEFT", +}; + +export const formatAlignmentCenterMenuItem: MenuItemSpec = { + name: _lt("Center"), + action: (env) => ACTIONS.setStyle(env, { align: "center" }), + icon: "o-spreadsheet-Icon.ALIGN_CENTER", +}; + +export const formatAlignmentRightMenuItem: MenuItemSpec = { + name: _lt("Right"), + action: (env) => ACTIONS.setStyle(env, { align: "right" }), + icon: "o-spreadsheet-Icon.ALIGN_RIGHT", +}; + +export const formatAlignmentTopMenuItem: MenuItemSpec = { + name: _lt("Top"), + action: (env) => ACTIONS.setStyle(env, { verticalAlign: "top" }), + icon: "o-spreadsheet-Icon.ALIGN_TOP", +}; + +export const formatAlignmentMiddleMenuItem: MenuItemSpec = { + name: _lt("Middle"), + action: (env) => ACTIONS.setStyle(env, { verticalAlign: "middle" }), + icon: "o-spreadsheet-Icon.ALIGN_MIDDLE", +}; + +export const formatAlignmentBottomMenuItem: MenuItemSpec = { + name: _lt("Bottom"), + action: (env) => ACTIONS.setStyle(env, { verticalAlign: "bottom" }), + icon: "o-spreadsheet-Icon.ALIGN_BOTTOM", +}; + +export const formatWrappingMenuItem: MenuItemSpec = { + name: _lt("Wrapping"), + icon: "o-spreadsheet-Icon.WRAPPING_OVERFLOW", +}; + +export const formatWrappingOverflowMenuItem: MenuItemSpec = { + name: _lt("Overflow"), + action: (env) => ACTIONS.setStyle(env, { wrapping: "overflow" }), + icon: "o-spreadsheet-Icon.WRAPPING_OVERFLOW", +}; + +export const formatWrappingWrapMenuItem: MenuItemSpec = { + name: _lt("Wrap"), + action: (env) => ACTIONS.setStyle(env, { wrapping: "wrap" }), + icon: "o-spreadsheet-Icon.WRAPPING_WRAP", +}; + +export const formatWrappingClipMenuItem: MenuItemSpec = { + name: _lt("Clip"), + action: (env) => ACTIONS.setStyle(env, { wrapping: "clip" }), + icon: "o-spreadsheet-Icon.WRAPPING_CLIP", +}; + +export const formatCFMenuItem: MenuItemSpec = { + name: _lt("Conditional formatting"), + action: ACTIONS.OPEN_CF_SIDEPANEL_ACTION, +}; + +export const clearFormatMenuItem: MenuItemSpec = { + name: _lt("Clear formatting"), + action: ACTIONS.FORMAT_CLEARFORMAT_ACTION, + icon: "o-spreadsheet-Icon.CLEAR_FORMAT", +}; + +function fontSizeMenuBuilder(): MenuItemSpec[] { + return FONT_SIZES.map((fs) => { + return { + name: fs.toString(), + sequence: fs, + id: `font_size_${fs}`, + action: (env) => ACTIONS.setStyle(env, { fontSize: fs }), + isActive: (env) => isFontSizeSelected(env, fs), + }; + }); +} + +function isAutomaticFormatSelected(env): boolean { + const activeCell = env.model.getters.getActiveCell(); + return !activeCell || !activeCell.format; +} + +function isFormatSelected(env, format: string): boolean { + const activeCell = env.model.getters.getActiveCell(); + return activeCell && activeCell.format === format; +} + +function isFontSizeSelected(env, fontSize: number): boolean { + const currentFontSize = env.model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE; + return currentFontSize === fontSize; +} diff --git a/src/registries/menus/items/insert_menu_items.ts b/src/registries/menus/items/insert_menu_items.ts new file mode 100644 index 0000000000..811a0c3f67 --- /dev/null +++ b/src/registries/menus/items/insert_menu_items.ts @@ -0,0 +1,164 @@ +import { functionRegistry } from "../../../functions"; +import { isDefined } from "../../../helpers"; +import { _lt } from "../../../translation"; +import { MenuItemsBuilder, MenuItemSpec } from "../../menu_items_registry"; +import * as ACTIONS from "./../menu_items_actions"; + +export const rowInsertRowBeforeMenuItem: MenuItemSpec = { + name: ACTIONS.ROW_INSERT_ROWS_BEFORE_NAME, + action: ACTIONS.INSERT_ROWS_BEFORE_ACTION, +}; + +export const topBarInsertRowsBeforeMenuItem: MenuItemSpec = { + ...rowInsertRowBeforeMenuItem, + name: ACTIONS.MENU_INSERT_ROWS_BEFORE_NAME, + isVisible: (env) => env.model.getters.getActiveCols().size === 0, +}; + +export const cellInsertRowsBeforeMenuItem: MenuItemSpec = { + ...rowInsertRowBeforeMenuItem, + name: ACTIONS.CELL_INSERT_ROWS_BEFORE_NAME, + isVisible: ACTIONS.IS_ONLY_ONE_RANGE, +}; + +export const rowInsertRowsAfterMenuItem: MenuItemSpec = { + action: ACTIONS.INSERT_ROWS_AFTER_ACTION, + name: ACTIONS.ROW_INSERT_ROWS_AFTER_NAME, +}; + +export const topBarInsertRowsAfterMenuItem: MenuItemSpec = { + ...rowInsertRowsAfterMenuItem, + name: ACTIONS.MENU_INSERT_ROWS_AFTER_NAME, + isVisible: (env) => env.model.getters.getActiveCols().size === 0, +}; + +export const colInsertColsBeforeMenuItem: MenuItemSpec = { + name: ACTIONS.COLUMN_INSERT_COLUMNS_BEFORE_NAME, + action: ACTIONS.INSERT_COLUMNS_BEFORE_ACTION, +}; + +export const topBarInsertColsBeforeMenuItem: MenuItemSpec = { + ...colInsertColsBeforeMenuItem, + name: ACTIONS.MENU_INSERT_COLUMNS_BEFORE_NAME, + isVisible: (env) => env.model.getters.getActiveRows().size === 0, +}; + +export const cellInsertColsBeforeMenuItem: MenuItemSpec = { + ...colInsertColsBeforeMenuItem, + name: ACTIONS.CELL_INSERT_COLUMNS_BEFORE_NAME, + isVisible: ACTIONS.IS_ONLY_ONE_RANGE, +}; + +export const colInsertColsAfterMenuItem: MenuItemSpec = { + name: ACTIONS.COLUMN_INSERT_COLUMNS_AFTER_NAME, + action: ACTIONS.INSERT_COLUMNS_AFTER_ACTION, +}; + +export const topBarInsertColsAfterMenuItem: MenuItemSpec = { + ...colInsertColsAfterMenuItem, + name: ACTIONS.MENU_INSERT_COLUMNS_AFTER_NAME, + action: ACTIONS.INSERT_COLUMNS_AFTER_ACTION, + isVisible: (env) => env.model.getters.getActiveRows().size === 0, +}; + +export const insertCellMenuItem: MenuItemSpec = { + name: _lt("Insert cells"), + isVisible: ACTIONS.IS_ONLY_ONE_RANGE, +}; + +export const insertCellShiftDownMenuItem: MenuItemSpec = { + name: _lt("Insert cells and shift down"), + action: ACTIONS.INSERT_CELL_SHIFT_DOWN, +}; + +export const insertCellShiftRightMenuItem: MenuItemSpec = { + name: _lt("Insert cells and shift right"), + action: ACTIONS.INSERT_CELL_SHIFT_RIGHT, +}; + +export const insertChartMenuItem: MenuItemSpec = { + name: _lt("Chart"), + action: ACTIONS.CREATE_CHART, +}; + +export const insertImageMenuItem: MenuItemSpec = { + name: _lt("Image"), + action: ACTIONS.CREATE_IMAGE, + isVisible: (env) => env.imageProvider !== undefined, +}; + +export const insertFunctionMenuItem: MenuItemSpec = { + name: _lt("Function"), +}; + +export const insertFunctionSumMenuItem: MenuItemSpec = { + name: _lt("SUM"), + action: (env) => env.startCellEdition(`=SUM(`), +}; + +export const insertFunctionAverageMenuItem: MenuItemSpec = { + name: _lt("AVERAGE"), + action: (env) => env.startCellEdition(`=AVERAGE(`), +}; + +export const insertFunctionCountMenuItem: MenuItemSpec = { + name: _lt("COUNT"), + action: (env) => env.startCellEdition(`=COUNT(`), +}; + +export const insertFunctionMaxMenuItem: MenuItemSpec = { + name: _lt("MAX"), + action: (env) => env.startCellEdition(`=MAX(`), +}; + +export const insertFunctionMinMenuItem: MenuItemSpec = { + name: _lt("MIN"), + action: (env) => env.startCellEdition(`=MIN(`), +}; + +export const categorieFunctionAllMenuItem: MenuItemSpec = { + name: _lt("All"), + children: allFunctionListMenuBuilder(), +}; + +function allFunctionListMenuBuilder(): MenuItemSpec[] { + const fnNames = functionRegistry.getKeys(); + return createFormulaFunctionMenuItems(fnNames); +} + +export const categoriesFunctionListMenuBuilder: MenuItemsBuilder = () => { + const functions = functionRegistry.content; + const categories = [...new Set(functionRegistry.getAll().map((fn) => fn.category))].filter( + isDefined + ); + + return categories.sort().map((category, i) => { + const functionsInCategory = Object.keys(functions).filter( + (key) => functions[key].category === category + ); + return { + name: category, + children: createFormulaFunctionMenuItems(functionsInCategory), + }; + }); +}; + +export const insertLinkMenuItem: MenuItemSpec = { + name: _lt("Link"), + action: ACTIONS.INSERT_LINK, +}; + +export const insertSheetMenuItem: MenuItemSpec = { + name: _lt("New sheet"), + action: ACTIONS.CREATE_SHEET_ACTION, +}; + +function createFormulaFunctionMenuItems(fnNames: string[]): MenuItemSpec[] { + return fnNames.sort().map((fnName, i) => { + return { + name: fnName, + sequence: i * 10, + action: (env) => env.startCellEdition(`=${fnName}(`), + }; + }); +} diff --git a/src/registries/menus/items/sheet_menu_items.ts b/src/registries/menus/items/sheet_menu_items.ts new file mode 100644 index 0000000000..59898242f2 --- /dev/null +++ b/src/registries/menus/items/sheet_menu_items.ts @@ -0,0 +1,84 @@ +import { buildSheetLink, markdownLink } from "../../../helpers"; +import { _lt } from "../../../translation"; +import { MenuItemSpec } from "../../menu_items_registry"; + +export const linkSheetMenuItem: MenuItemSpec = { + name: _lt("Link sheet"), + children: [ + (env) => { + const sheets = env.model.getters + .getSheetIds() + .map((sheetId) => env.model.getters.getSheet(sheetId)); + return sheets.map((sheet) => ({ + id: sheet.id, + name: sheet.name, + action: () => markdownLink(sheet.name, buildSheetLink(sheet.id)), + })); + }, + ], +}; + +export const deleteSheetMenuItem: MenuItemSpec = { + name: _lt("Delete"), + isVisible: (env) => { + return env.model.getters.getSheetIds().length > 1; + }, + action: (env) => + env.askConfirmation(_lt("Are you sure you want to delete this sheet ?"), () => { + env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() }); + }), +}; + +export const duplicateSheetMenuItem: MenuItemSpec = { + name: _lt("Duplicate"), + action: (env) => { + const sheetIdFrom = env.model.getters.getActiveSheetId(); + const sheetIdTo = env.model.uuidGenerator.uuidv4(); + env.model.dispatch("DUPLICATE_SHEET", { + sheetId: sheetIdFrom, + sheetIdTo, + }); + env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo }); + }, +}; + +export const renameSheetMenuItem = (args: { renameSheetCallback: () => void }): MenuItemSpec => { + return { + name: _lt("Rename"), + action: args.renameSheetCallback, + }; +}; + +export const sheetMoveRightMenuItem: MenuItemSpec = { + name: _lt("Move right"), + isVisible: (env) => { + const sheetId = env.model.getters.getActiveSheetId(); + const sheetIds = env.model.getters.getVisibleSheetIds(); + return sheetIds.indexOf(sheetId) !== sheetIds.length - 1; + }, + action: (env) => + env.model.dispatch("MOVE_SHEET", { + sheetId: env.model.getters.getActiveSheetId(), + delta: 1, + }), +}; + +export const sheetMoveLeftMenuItem: MenuItemSpec = { + name: _lt("Move left"), + isVisible: (env) => { + const sheetId = env.model.getters.getActiveSheetId(); + return env.model.getters.getVisibleSheetIds()[0] !== sheetId; + }, + action: (env) => + env.model.dispatch("MOVE_SHEET", { + sheetId: env.model.getters.getActiveSheetId(), + delta: -1, + }), +}; + +export const hideSheetMenuItem: MenuItemSpec = { + name: _lt("Hide sheet"), + isVisible: (env) => env.model.getters.getVisibleSheetIds().length !== 1, + action: (env) => + env.model.dispatch("HIDE_SHEET", { sheetId: env.model.getters.getActiveSheetId() }), +}; diff --git a/src/registries/menus/items/view_menu_items.ts b/src/registries/menus/items/view_menu_items.ts new file mode 100644 index 0000000000..73d7b34266 --- /dev/null +++ b/src/registries/menus/items/view_menu_items.ts @@ -0,0 +1,166 @@ +import { interactiveFreezeColumnsRows } from "../../../helpers/ui/freeze_interactive"; +import { _lt } from "../../../translation"; +import { SpreadsheetChildEnv } from "../../../types"; +import { MenuItemSpec } from "../../menu_items_registry"; +import * as ACTIONS from "./../menu_items_actions"; + +export const hideColsMenuItem: MenuItemSpec = { + name: ACTIONS.HIDE_COLUMNS_NAME, + action: ACTIONS.HIDE_COLUMNS_ACTION, + isVisible: (env: SpreadsheetChildEnv) => { + const sheetId = env.model.getters.getActiveSheetId(); + const hiddenCols = env.model.getters.getHiddenColsGroups(sheetId).flat(); + return ( + env.model.getters.getNumberCols(sheetId) > + hiddenCols.length + env.model.getters.getElementsFromSelection("COL").length + ); + }, +}; + +export const unhideColsMenuItem: MenuItemSpec = { + name: _lt("Unhide columns"), + action: ACTIONS.UNHIDE_COLUMNS_ACTION, + isVisible: (env: SpreadsheetChildEnv) => { + const hiddenCols = env.model.getters + .getHiddenColsGroups(env.model.getters.getActiveSheetId()) + .flat(); + const currentCols = env.model.getters.getElementsFromSelection("COL"); + return currentCols.some((col) => hiddenCols.includes(col)); + }, +}; + +export const unhideAllColsMenuItem: MenuItemSpec = { + name: _lt("Unhide all columns"), + action: ACTIONS.UNHIDE_ALL_COLUMNS_ACTION, + isVisible: (env: SpreadsheetChildEnv) => + env.model.getters.getHiddenColsGroups(env.model.getters.getActiveSheetId()).length > 0, +}; + +export const hideRowsMenuItem: MenuItemSpec = { + name: ACTIONS.HIDE_ROWS_NAME, + action: ACTIONS.HIDE_ROWS_ACTION, + isVisible: (env: SpreadsheetChildEnv) => { + const sheetId = env.model.getters.getActiveSheetId(); + const hiddenRows = env.model.getters.getHiddenRowsGroups(sheetId).flat(); + return ( + env.model.getters.getNumberRows(sheetId) > + hiddenRows.length + env.model.getters.getElementsFromSelection("ROW").length + ); + }, +}; + +export const unhideRowsMenuItem: MenuItemSpec = { + name: _lt("Unhide rows"), + action: ACTIONS.UNHIDE_ROWS_ACTION, + isVisible: (env: SpreadsheetChildEnv) => { + const hiddenRows = env.model.getters + .getHiddenRowsGroups(env.model.getters.getActiveSheetId()) + .flat(); + const currentRows = env.model.getters.getElementsFromSelection("ROW"); + return currentRows.some((col) => hiddenRows.includes(col)); + }, +}; + +export const unhideAllRowsMenuItem: MenuItemSpec = { + name: _lt("Unhide all rows"), + action: ACTIONS.UNHIDE_ALL_ROWS_ACTION, + isVisible: (env: SpreadsheetChildEnv) => + env.model.getters.getHiddenRowsGroups(env.model.getters.getActiveSheetId()).length > 0, +}; + +export const unFreezePaneMenuItem: MenuItemSpec = { + name: _lt("Unfreeze"), + isVisible: (env) => { + const { xSplit, ySplit } = env.model.getters.getPaneDivisions( + env.model.getters.getActiveSheetId() + ); + return xSplit + ySplit > 0; + }, + action: (env) => + env.model.dispatch("UNFREEZE_COLUMNS_ROWS", { + sheetId: env.model.getters.getActiveSheetId(), + }), +}; + +export const freezePaneMenuItem: MenuItemSpec = { + name: _lt("Freeze"), +}; + +export const unFreezeRowsMenuItem: MenuItemSpec = { + name: _lt("No rows"), + action: (env) => + env.model.dispatch("UNFREEZE_ROWS", { + sheetId: env.model.getters.getActiveSheetId(), + }), + isReadonlyAllowed: true, + isVisible: (env) => + !!env.model.getters.getPaneDivisions(env.model.getters.getActiveSheetId()).ySplit, +}; + +export const freezeFirstRowMenuItem: MenuItemSpec = { + name: _lt("1 row"), + action: (env) => interactiveFreezeColumnsRows(env, "ROW", 1), + isReadonlyAllowed: true, +}; + +export const freezeSecondRowMenuItem: MenuItemSpec = { + name: _lt("2 rows"), + action: (env) => interactiveFreezeColumnsRows(env, "ROW", 2), + isReadonlyAllowed: true, +}; + +export const freezeCurrentRowMenuItem: MenuItemSpec = { + name: _lt("Up to current row"), + action: (env) => { + const { bottom } = env.model.getters.getSelectedZone(); + interactiveFreezeColumnsRows(env, "ROW", bottom + 1); + }, + isReadonlyAllowed: true, +}; + +export const unFreezeColsMenuItem: MenuItemSpec = { + name: _lt("No columns"), + action: (env) => + env.model.dispatch("UNFREEZE_COLUMNS", { + sheetId: env.model.getters.getActiveSheetId(), + }), + isReadonlyAllowed: true, + isVisible: (env) => + !!env.model.getters.getPaneDivisions(env.model.getters.getActiveSheetId()).xSplit, +}; + +export const freezeFirstColMenuItem: MenuItemSpec = { + name: _lt("1 column"), + action: (env) => interactiveFreezeColumnsRows(env, "COL", 1), + isReadonlyAllowed: true, +}; + +export const freezeSecondColMenuItem: MenuItemSpec = { + name: _lt("2 columns"), + action: (env) => interactiveFreezeColumnsRows(env, "COL", 2), + isReadonlyAllowed: true, +}; + +export const freezeCurrentColMenuItem: MenuItemSpec = { + name: _lt("Up to current column"), + action: (env) => { + const { right } = env.model.getters.getSelectedZone(); + interactiveFreezeColumnsRows(env, "COL", right + 1); + }, + isReadonlyAllowed: true, +}; + +export const viewGridlinesMenuItem: MenuItemSpec = { + name: (env: SpreadsheetChildEnv) => + env.model.getters.getGridLinesVisibility(env.model.getters.getActiveSheetId()) + ? _lt("Hide gridlines") + : _lt("Show gridlines"), + action: ACTIONS.SET_GRID_LINES_VISIBILITY_ACTION, +}; + +export const viewFormulasMenuItem: MenuItemSpec = { + name: (env: SpreadsheetChildEnv) => + env.model.getters.shouldShowFormulas() ? _lt("Hide formulas") : _lt("Show formulas"), + action: ACTIONS.SET_FORMULA_VISIBILITY_ACTION, + isReadonlyAllowed: true, +}; diff --git a/src/registries/menus/link_menu_registry.ts b/src/registries/menus/link_menu_registry.ts index b7a77458be..3c81daa37c 100644 --- a/src/registries/menus/link_menu_registry.ts +++ b/src/registries/menus/link_menu_registry.ts @@ -1,6 +1,5 @@ -import { buildSheetLink, markdownLink } from "../../helpers"; -import { _lt } from "../../translation"; import { MenuItemRegistry } from "../menu_items_registry"; +import * as ACTION_SHEET from "./items/sheet_menu_items"; //------------------------------------------------------------------------------ // Link Menu Registry @@ -8,18 +7,7 @@ import { MenuItemRegistry } from "../menu_items_registry"; export const linkMenuRegistry = new MenuItemRegistry(); -linkMenuRegistry - .add("sheet", { - name: _lt("Link sheet"), - sequence: 10, - }) - .addChild("sheet_list", ["sheet"], (env) => { - const sheets = env.model.getters - .getSheetIds() - .map((sheetId) => env.model.getters.getSheet(sheetId)); - return sheets.map((sheet) => ({ - id: sheet.id, - name: sheet.name, - action: () => markdownLink(sheet.name, buildSheetLink(sheet.id)), - })); - }); +linkMenuRegistry.add("sheet", { + ...ACTION_SHEET.linkSheetMenuItem, + sequence: 10, +}); diff --git a/src/registries/menus/row_menu_registry.ts b/src/registries/menus/row_menu_registry.ts index 436f50f343..9452835513 100644 --- a/src/registries/menus/row_menu_registry.ts +++ b/src/registries/menus/row_menu_registry.ts @@ -1,95 +1,64 @@ -import { _lt } from "../../translation"; -import { SpreadsheetChildEnv } from "../../types"; import { MenuItemRegistry } from "../menu_items_registry"; -import * as ACTIONS from "./menu_items_actions"; +import * as ACTION_EDIT from "./items/edit_menu_items"; +import * as ACTION_FORMAT from "./items/format_menu_items"; +import * as ACTION_INSERT from "./items/insert_menu_items"; +import * as ACTION_VIEW from "./items/view_menu_items"; export const rowMenuRegistry = new MenuItemRegistry(); rowMenuRegistry .add("cut", { - name: _lt("Cut"), + ...ACTION_EDIT.cutMenuItem, sequence: 10, - description: "Ctrl+X", - action: ACTIONS.CUT_ACTION, }) .add("copy", { - name: _lt("Copy"), - description: "Ctrl+C", + ...ACTION_EDIT.copyMenuItem, sequence: 20, - isReadonlyAllowed: true, - action: ACTIONS.COPY_ACTION, }) .add("paste", { - name: _lt("Paste"), - description: "Ctrl+V", + ...ACTION_EDIT.pasteMenuItem, sequence: 30, - action: ACTIONS.PASTE_ACTION, }) .add("paste_special", { - name: _lt("Paste special"), + ...ACTION_EDIT.pasteSpecialMenuItem, sequence: 40, separator: true, - isVisible: ACTIONS.IS_NOT_CUT_OPERATION, }) .addChild("paste_value_only", ["paste_special"], { - name: _lt("Paste value only"), + ...ACTION_EDIT.pasteSpecialValueMenuItem, sequence: 10, - action: ACTIONS.PASTE_VALUE_ACTION, }) .addChild("paste_format_only", ["paste_special"], { - name: _lt("Paste format only"), + ...ACTION_EDIT.pasteSpecialFormatMenuItem, sequence: 20, - action: ACTIONS.PASTE_FORMAT_ACTION, }) .add("add_row_before", { - name: ACTIONS.ROW_INSERT_ROWS_BEFORE_NAME, + ...ACTION_INSERT.rowInsertRowBeforeMenuItem, sequence: 50, - action: ACTIONS.INSERT_ROWS_BEFORE_ACTION, }) .add("add_row_after", { - name: ACTIONS.ROW_INSERT_ROWS_AFTER_NAME, + ...ACTION_INSERT.rowInsertRowsAfterMenuItem, sequence: 60, - action: ACTIONS.INSERT_ROWS_AFTER_ACTION, }) .add("delete_row", { - name: ACTIONS.REMOVE_ROWS_NAME, + ...ACTION_EDIT.deleteRowsMenuItem, sequence: 70, - action: ACTIONS.REMOVE_ROWS_ACTION, }) .add("clear_row", { - name: ACTIONS.DELETE_CONTENT_ROWS_NAME, + ...ACTION_EDIT.clearRowsMenuItem, sequence: 80, - action: ACTIONS.DELETE_CONTENT_ROWS_ACTION, }) .add("hide_rows", { - name: ACTIONS.HIDE_ROWS_NAME, + ...ACTION_VIEW.hideRowsMenuItem, sequence: 85, - action: ACTIONS.HIDE_ROWS_ACTION, - isVisible: (env: SpreadsheetChildEnv) => { - const sheetId = env.model.getters.getActiveSheetId(); - const hiddenRows = env.model.getters.getHiddenRowsGroups(sheetId).flat(); - return ( - env.model.getters.getNumberRows(sheetId) > - hiddenRows.length + env.model.getters.getElementsFromSelection("ROW").length - ); - }, separator: true, }) .add("unhide_rows", { - name: _lt("Unhide rows"), + ...ACTION_VIEW.unhideRowsMenuItem, sequence: 86, - action: ACTIONS.UNHIDE_ROWS_ACTION, - isVisible: (env: SpreadsheetChildEnv) => { - const hiddenRows = env.model.getters - .getHiddenRowsGroups(env.model.getters.getActiveSheetId()) - .flat(); - const currentRows = env.model.getters.getElementsFromSelection("ROW"); - return currentRows.some((col) => hiddenRows.includes(col)); - }, separator: true, }) .add("conditional_formatting", { - name: _lt("Conditional formatting"), + ...ACTION_FORMAT.formatCFMenuItem, sequence: 90, - action: ACTIONS.OPEN_CF_SIDEPANEL_ACTION, }); diff --git a/src/registries/menus/sheet_menu_registry.ts b/src/registries/menus/sheet_menu_registry.ts index 66f0467b31..b9b5be69ad 100644 --- a/src/registries/menus/sheet_menu_registry.ts +++ b/src/registries/menus/sheet_menu_registry.ts @@ -1,72 +1,33 @@ -import { _lt } from "../../translation"; import { MenuItemRegistry } from "../menu_items_registry"; +import * as ACTION_SHEET from "./items/sheet_menu_items"; export function getSheetMenuRegistry(args: { renameSheetCallback: () => void }): MenuItemRegistry { const sheetMenuRegistry = new MenuItemRegistry(); sheetMenuRegistry .add("delete", { - name: _lt("Delete"), + ...ACTION_SHEET.deleteSheetMenuItem, sequence: 10, - isVisible: (env) => { - return env.model.getters.getSheetIds().length > 1; - }, - action: (env) => - env.askConfirmation(_lt("Are you sure you want to delete this sheet ?"), () => { - env.model.dispatch("DELETE_SHEET", { sheetId: env.model.getters.getActiveSheetId() }); - }), }) .add("duplicate", { - name: _lt("Duplicate"), + ...ACTION_SHEET.duplicateSheetMenuItem, sequence: 20, - action: (env) => { - const sheetIdFrom = env.model.getters.getActiveSheetId(); - const sheetIdTo = env.model.uuidGenerator.uuidv4(); - env.model.dispatch("DUPLICATE_SHEET", { - sheetId: sheetIdFrom, - sheetIdTo, - }); - env.model.dispatch("ACTIVATE_SHEET", { sheetIdFrom, sheetIdTo }); - }, }) .add("rename", { - name: _lt("Rename"), + ...ACTION_SHEET.renameSheetMenuItem(args), sequence: 30, - action: () => args.renameSheetCallback(), }) .add("move_right", { - name: _lt("Move right"), + ...ACTION_SHEET.sheetMoveRightMenuItem, sequence: 40, - isVisible: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - const sheetIds = env.model.getters.getVisibleSheetIds(); - return sheetIds.indexOf(sheetId) !== sheetIds.length - 1; - }, - action: (env) => - env.model.dispatch("MOVE_SHEET", { - sheetId: env.model.getters.getActiveSheetId(), - delta: 1, - }), }) .add("move_left", { - name: _lt("Move left"), + ...ACTION_SHEET.sheetMoveLeftMenuItem, sequence: 50, - isVisible: (env) => { - const sheetId = env.model.getters.getActiveSheetId(); - return env.model.getters.getVisibleSheetIds()[0] !== sheetId; - }, - action: (env) => - env.model.dispatch("MOVE_SHEET", { - sheetId: env.model.getters.getActiveSheetId(), - delta: -1, - }), }) .add("hide_sheet", { - name: _lt("Hide sheet"), + ...ACTION_SHEET.hideSheetMenuItem, sequence: 60, - isVisible: (env) => env.model.getters.getVisibleSheetIds().length !== 1, - action: (env) => - env.model.dispatch("HIDE_SHEET", { sheetId: env.model.getters.getActiveSheetId() }), }); return sheetMenuRegistry; diff --git a/src/registries/menus/topbar_menu_registry.ts b/src/registries/menus/topbar_menu_registry.ts index e4d1240565..a5337d5844 100644 --- a/src/registries/menus/topbar_menu_registry.ts +++ b/src/registries/menus/topbar_menu_registry.ts @@ -1,587 +1,407 @@ -import { NumberFormatTerms } from "../../components/translations_terms"; -import { DEFAULT_FONT_SIZE, FONT_SIZES } from "../../constants"; -import { functionRegistry } from "../../functions/index"; -import { isDefined } from "../../helpers"; -import { interactiveFreezeColumnsRows } from "../../helpers/ui/freeze_interactive"; import { _lt } from "../../translation"; -import { SpreadsheetChildEnv } from "../../types/env"; -import { MenuItemRegistry, MenuItemSpec } from "../menu_items_registry"; -import * as ACTIONS from "./menu_items_actions"; -import { setStyle } from "./menu_items_actions"; +import { MenuItemRegistry } from "../menu_items_registry"; +import * as ACTION_DATA from "./items/data_menu_items"; +import * as ACTION_EDIT from "./items/edit_menu_items"; +import * as ACTION_FORMAT from "./items/format_menu_items"; +import * as ACTION_INSERT from "./items/insert_menu_items"; +import * as ACTION_VIEW from "./items/view_menu_items"; export const topbarMenuRegistry = new MenuItemRegistry(); topbarMenuRegistry - .add("file", { name: _lt("File"), sequence: 10 }) - .add("edit", { name: _lt("Edit"), sequence: 20 }) - .add("view", { name: _lt("View"), sequence: 30 }) - .add("insert", { name: _lt("Insert"), sequence: 40 }) - .add("format", { name: _lt("Format"), sequence: 50 }) - .add("data", { name: _lt("Data"), sequence: 60 }) + + // --------------------------------------------------------------------- + // FILE MENU ITEMS + // --------------------------------------------------------------------- + + .add("file", { + name: _lt("File"), + sequence: 10, + }) + + // --------------------------------------------------------------------- + // EDIT MENU ITEMS + // --------------------------------------------------------------------- + + .add("edit", { + name: _lt("Edit"), + sequence: 20, + }) .addChild("undo", ["edit"], { - name: _lt("Undo"), - description: "Ctrl+Z", + ...ACTION_EDIT.undoMenuItem, sequence: 10, - action: ACTIONS.UNDO_ACTION, - icon: "o-spreadsheet-Icon.UNDO", }) .addChild("redo", ["edit"], { - name: _lt("Redo"), - description: "Ctrl+Y", + ...ACTION_EDIT.redoMenuItem, sequence: 20, - action: ACTIONS.REDO_ACTION, - icon: "o-spreadsheet-Icon.REDO", separator: true, }) .addChild("copy", ["edit"], { - name: _lt("Copy"), - description: "Ctrl+C", + ...ACTION_EDIT.copyMenuItem, sequence: 30, - isReadonlyAllowed: true, - action: ACTIONS.COPY_ACTION, }) .addChild("cut", ["edit"], { - name: _lt("Cut"), - description: "Ctrl+X", + ...ACTION_EDIT.cutMenuItem, sequence: 40, - action: ACTIONS.CUT_ACTION, }) .addChild("paste", ["edit"], { - name: _lt("Paste"), - description: "Ctrl+V", + ...ACTION_EDIT.pasteMenuItem, sequence: 50, - action: ACTIONS.PASTE_ACTION, }) .addChild("paste_special", ["edit"], { - name: _lt("Paste special"), + ...ACTION_EDIT.pasteSpecialMenuItem, sequence: 60, separator: true, - isVisible: ACTIONS.IS_NOT_CUT_OPERATION, }) .addChild("paste_special_value", ["edit", "paste_special"], { - name: _lt("Paste value only"), + ...ACTION_EDIT.pasteSpecialValueMenuItem, sequence: 10, - action: ACTIONS.PASTE_VALUE_ACTION, }) .addChild("paste_special_format", ["edit", "paste_special"], { - name: _lt("Paste format only"), + ...ACTION_EDIT.pasteSpecialFormatMenuItem, sequence: 20, - action: ACTIONS.PASTE_FORMAT_ACTION, - }) - .addChild("sort_range", ["data"], { - name: _lt("Sort range"), - sequence: 20, - isVisible: ACTIONS.IS_ONLY_ONE_RANGE, - separator: true, - }) - .addChild("sort_ascending", ["data", "sort_range"], { - name: _lt("Ascending (A ⟶ Z)"), - sequence: 10, - action: ACTIONS.SORT_CELLS_ASCENDING, - }) - .addChild("sort_descending", ["data", "sort_range"], { - name: _lt("Descending (Z ⟶ A)"), - sequence: 20, - action: ACTIONS.SORT_CELLS_DESCENDING, }) .addChild("find_and_replace", ["edit"], { - name: _lt("Find and replace"), - description: "Ctrl+H", + ...ACTION_EDIT.findAndReplaceMenuItem, sequence: 65, - isReadonlyAllowed: true, - action: ACTIONS.OPEN_FAR_SIDEPANEL_ACTION, separator: true, }) .addChild("edit_delete_cell_values", ["edit"], { - name: _lt("Delete values"), + ...ACTION_EDIT.deleteValuesMenuItem, sequence: 70, - action: ACTIONS.DELETE_CONTENT_ACTION, }) .addChild("edit_delete_row", ["edit"], { - name: ACTIONS.REMOVE_ROWS_NAME, + ...ACTION_EDIT.deleteRowsMenuItem, sequence: 80, - action: ACTIONS.REMOVE_ROWS_ACTION, }) .addChild("edit_delete_column", ["edit"], { - name: ACTIONS.REMOVE_COLUMNS_NAME, + ...ACTION_EDIT.deleteColsMenuItem, sequence: 90, - action: ACTIONS.REMOVE_COLUMNS_ACTION, }) .addChild("edit_delete_cell_shift_up", ["edit"], { - name: _lt("Delete cell and shift up"), + ...ACTION_EDIT.deleteCellShiftUpMenuItem, sequence: 93, - action: ACTIONS.DELETE_CELL_SHIFT_UP, }) .addChild("edit_delete_cell_shift_left", ["edit"], { - name: _lt("Delete cell and shift left"), + ...ACTION_EDIT.deleteCellShiftLeftMenuItem, sequence: 97, - action: ACTIONS.DELETE_CELL_SHIFT_LEFT, }) .addChild("edit_unhide_columns", ["edit"], { - name: _lt("Unhide all columns"), + ...ACTION_VIEW.unhideAllColsMenuItem, sequence: 100, - action: ACTIONS.UNHIDE_ALL_COLUMNS_ACTION, - isVisible: (env: SpreadsheetChildEnv) => - env.model.getters.getHiddenColsGroups(env.model.getters.getActiveSheetId()).length > 0, }) .addChild("edit_unhide_rows", ["edit"], { - name: _lt("Unhide all rows"), + ...ACTION_VIEW.unhideAllRowsMenuItem, sequence: 100, - action: ACTIONS.UNHIDE_ALL_ROWS_ACTION, - isVisible: (env: SpreadsheetChildEnv) => - env.model.getters.getHiddenRowsGroups(env.model.getters.getActiveSheetId()).length > 0, + }) + + // --------------------------------------------------------------------- + // VIEW MENU ITEMS + // --------------------------------------------------------------------- + + .add("view", { + name: _lt("View"), + sequence: 30, + }) + .addChild("unfreeze_panes", ["view"], { + ...ACTION_VIEW.unFreezePaneMenuItem, + sequence: 4, + }) + .addChild("freeze_panes", ["view"], { + ...ACTION_VIEW.freezePaneMenuItem, + sequence: 5, + separator: true, + }) + .addChild("unfreeze_rows", ["view", "freeze_panes"], { + ...ACTION_VIEW.unFreezeRowsMenuItem, + sequence: 5, + }) + .addChild("freeze_first_row", ["view", "freeze_panes"], { + ...ACTION_VIEW.freezeFirstRowMenuItem, + sequence: 10, + }) + .addChild("freeze_second_row", ["view", "freeze_panes"], { + ...ACTION_VIEW.freezeSecondRowMenuItem, + sequence: 15, + }) + .addChild("freeze_current_row", ["view", "freeze_panes"], { + ...ACTION_VIEW.freezeCurrentRowMenuItem, + sequence: 20, + separator: true, + }) + .addChild("unfreeze_columns", ["view", "freeze_panes"], { + ...ACTION_VIEW.unFreezeColsMenuItem, + sequence: 25, + }) + .addChild("freeze_first_col", ["view", "freeze_panes"], { + ...ACTION_VIEW.freezeFirstColMenuItem, + sequence: 30, + }) + .addChild("freeze_second_col", ["view", "freeze_panes"], { + ...ACTION_VIEW.freezeSecondColMenuItem, + sequence: 35, + }) + .addChild("freeze_current_col", ["view", "freeze_panes"], { + ...ACTION_VIEW.freezeCurrentColMenuItem, + sequence: 40, + }) + .addChild("view_gridlines", ["view"], { + ...ACTION_VIEW.viewGridlinesMenuItem, + sequence: 10, + }) + .addChild("view_formulas", ["view"], { + ...ACTION_VIEW.viewFormulasMenuItem, + sequence: 15, + }) + + // --------------------------------------------------------------------- + // INSERT MENU ITEMS + // --------------------------------------------------------------------- + + .add("insert", { + name: _lt("Insert"), + sequence: 40, }) .addChild("insert_row_before", ["insert"], { - name: ACTIONS.MENU_INSERT_ROWS_BEFORE_NAME, + ...ACTION_INSERT.topBarInsertRowsBeforeMenuItem, sequence: 10, - action: ACTIONS.INSERT_ROWS_BEFORE_ACTION, - isVisible: (env: SpreadsheetChildEnv) => env.model.getters.getActiveCols().size === 0, }) .addChild("insert_row_after", ["insert"], { - name: ACTIONS.MENU_INSERT_ROWS_AFTER_NAME, + ...ACTION_INSERT.topBarInsertRowsAfterMenuItem, sequence: 20, - action: ACTIONS.INSERT_ROWS_AFTER_ACTION, - isVisible: (env: SpreadsheetChildEnv) => env.model.getters.getActiveCols().size === 0, separator: true, }) .addChild("insert_column_before", ["insert"], { - name: ACTIONS.MENU_INSERT_COLUMNS_BEFORE_NAME, + ...ACTION_INSERT.topBarInsertColsBeforeMenuItem, sequence: 30, - action: ACTIONS.INSERT_COLUMNS_BEFORE_ACTION, - isVisible: (env: SpreadsheetChildEnv) => env.model.getters.getActiveRows().size === 0, }) .addChild("insert_column_after", ["insert"], { - name: ACTIONS.MENU_INSERT_COLUMNS_AFTER_NAME, + ...ACTION_INSERT.topBarInsertColsAfterMenuItem, sequence: 40, - action: ACTIONS.INSERT_COLUMNS_AFTER_ACTION, - isVisible: (env: SpreadsheetChildEnv) => env.model.getters.getActiveRows().size === 0, separator: true, }) .addChild("insert_insert_cell_shift_down", ["insert"], { - name: _lt("Insert cells and shift down"), + ...ACTION_INSERT.insertCellShiftDownMenuItem, sequence: 43, - action: ACTIONS.INSERT_CELL_SHIFT_DOWN, }) .addChild("insert_insert_cell_shift_right", ["insert"], { - name: _lt("Insert cells and shift right"), + ...ACTION_INSERT.insertCellShiftRightMenuItem, sequence: 47, - action: ACTIONS.INSERT_CELL_SHIFT_RIGHT, separator: true, }) .addChild("insert_chart", ["insert"], { - name: _lt("Chart"), + ...ACTION_INSERT.insertChartMenuItem, sequence: 50, - action: ACTIONS.CREATE_CHART, }) .addChild("insert_image", ["insert"], { - name: _lt("Image"), + ...ACTION_INSERT.insertImageMenuItem, sequence: 55, - action: ACTIONS.CREATE_IMAGE, - isVisible: (env: SpreadsheetChildEnv) => env.imageProvider !== undefined, }) .addChild("insert_function", ["insert"], { - name: _lt("Function"), + ...ACTION_INSERT.insertFunctionMenuItem, sequence: 60, }) .addChild("insert_function_sum", ["insert", "insert_function"], { - name: _lt("SUM"), - action: (env) => env.startCellEdition(`=SUM(`), + ...ACTION_INSERT.insertFunctionSumMenuItem, sequence: 0, }) .addChild("insert_function_average", ["insert", "insert_function"], { - name: _lt("AVERAGE"), - action: (env) => env.startCellEdition(`=AVERAGE(`), + ...ACTION_INSERT.insertFunctionAverageMenuItem, sequence: 10, }) .addChild("insert_function_count", ["insert", "insert_function"], { - name: _lt("COUNT"), - action: (env) => env.startCellEdition(`=COUNT(`), + ...ACTION_INSERT.insertFunctionCountMenuItem, sequence: 20, }) .addChild("insert_function_max", ["insert", "insert_function"], { - name: _lt("MAX"), - action: (env) => env.startCellEdition(`=MAX(`), + ...ACTION_INSERT.insertFunctionMaxMenuItem, sequence: 30, }) .addChild("insert_function_min", ["insert", "insert_function"], { - name: _lt("MIN"), - action: (env) => env.startCellEdition(`=MIN(`), + ...ACTION_INSERT.insertFunctionMinMenuItem, sequence: 40, separator: true, }) .addChild("categorie_function_all", ["insert", "insert_function"], { - name: _lt("All"), + ...ACTION_INSERT.categorieFunctionAllMenuItem, sequence: 50, }) - .addChild("all_function_list", ["insert", "insert_function", "categorie_function_all"], () => { - const fnNames = functionRegistry.getKeys(); - return createFormulaFunctionMenuItems(fnNames); - }) - .addChild("categories_function_list", ["insert", "insert_function"], () => { - const functions = functionRegistry.content; - const categories = [...new Set(functionRegistry.getAll().map((fn) => fn.category))].filter( - isDefined - ); - - return categories.sort().map((category, i) => { - const functionsInCategory = Object.keys(functions).filter( - (key) => functions[key].category === category - ); - return { - name: category, - sequence: 60 + i * 10, - children: createFormulaFunctionMenuItems(functionsInCategory), - }; - }); - }) + .addChild( + "categories_function_list", + ["insert", "insert_function"], + ACTION_INSERT.categoriesFunctionListMenuBuilder + ) .addChild("insert_link", ["insert"], { - name: _lt("Link"), + ...ACTION_INSERT.insertLinkMenuItem, separator: true, sequence: 70, - action: ACTIONS.INSERT_LINK, }) .addChild("insert_sheet", ["insert"], { - name: _lt("New sheet"), + ...ACTION_INSERT.insertSheetMenuItem, sequence: 80, - action: ACTIONS.CREATE_SHEET_ACTION, separator: true, }) - .addChild("unfreeze_panes", ["view"], { - name: _lt("Unfreeze"), - sequence: 4, - isVisible: (env) => { - const { xSplit, ySplit } = env.model.getters.getPaneDivisions( - env.model.getters.getActiveSheetId() - ); - return xSplit + ySplit > 0; - }, - action: (env) => - env.model.dispatch("UNFREEZE_COLUMNS_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), - }), - }) - .addChild("freeze_panes", ["view"], { - name: _lt("Freeze"), - sequence: 5, - separator: true, - }) - .addChild("unfreeze_rows", ["view", "freeze_panes"], { - name: _lt("No rows"), - action: (env) => - env.model.dispatch("UNFREEZE_ROWS", { - sheetId: env.model.getters.getActiveSheetId(), - }), - isReadonlyAllowed: true, - sequence: 5, - isVisible: (env) => - !!env.model.getters.getPaneDivisions(env.model.getters.getActiveSheetId()).ySplit, - }) - .addChild("freeze_first_row", ["view", "freeze_panes"], { - name: _lt("1 row"), - action: (env) => interactiveFreezeColumnsRows(env, "ROW", 1), - isReadonlyAllowed: true, - sequence: 10, - }) - .addChild("freeze_second_row", ["view", "freeze_panes"], { - name: _lt("2 rows"), - action: (env) => interactiveFreezeColumnsRows(env, "ROW", 2), - isReadonlyAllowed: true, - sequence: 15, - }) - .addChild("freeze_current_row", ["view", "freeze_panes"], { - name: _lt("Up to current row"), - action: (env) => { - const { bottom } = env.model.getters.getSelectedZone(); - interactiveFreezeColumnsRows(env, "ROW", bottom + 1); - }, - isReadonlyAllowed: true, - sequence: 20, - separator: true, - }) - .addChild("unfreeze_columns", ["view", "freeze_panes"], { - name: _lt("No columns"), - action: (env) => - env.model.dispatch("UNFREEZE_COLUMNS", { - sheetId: env.model.getters.getActiveSheetId(), - }), - isReadonlyAllowed: true, - sequence: 25, - isVisible: (env) => - !!env.model.getters.getPaneDivisions(env.model.getters.getActiveSheetId()).xSplit, - }) - .addChild("freeze_first_col", ["view", "freeze_panes"], { - name: _lt("1 column"), - action: (env) => interactiveFreezeColumnsRows(env, "COL", 1), - isReadonlyAllowed: true, - sequence: 30, - }) - .addChild("freeze_second_col", ["view", "freeze_panes"], { - name: _lt("2 columns"), - action: (env) => interactiveFreezeColumnsRows(env, "COL", 2), - isReadonlyAllowed: true, - sequence: 35, - }) - .addChild("freeze_current_col", ["view", "freeze_panes"], { - name: _lt("Up to current column"), - action: (env) => { - const { right } = env.model.getters.getSelectedZone(); - interactiveFreezeColumnsRows(env, "COL", right + 1); - }, - isReadonlyAllowed: true, - sequence: 40, - }) - .addChild("view_gridlines", ["view"], { - name: (env: SpreadsheetChildEnv) => - env.model.getters.getGridLinesVisibility(env.model.getters.getActiveSheetId()) - ? _lt("Hide gridlines") - : _lt("Show gridlines"), - action: ACTIONS.SET_GRID_LINES_VISIBILITY_ACTION, - sequence: 10, - }) - .addChild("view_formulas", ["view"], { - name: (env: SpreadsheetChildEnv) => - env.model.getters.shouldShowFormulas() ? _lt("Hide formulas") : _lt("Show formulas"), - action: ACTIONS.SET_FORMULA_VISIBILITY_ACTION, - isReadonlyAllowed: true, - sequence: 15, - }) + + // --------------------------------------------------------------------- + // FORMAT MENU ITEMS + // --------------------------------------------------------------------- + + .add("format", { name: _lt("Format"), sequence: 50 }) .addChild("format_number", ["format"], { - name: _lt("Numbers"), + ...ACTION_FORMAT.formatNumberMenuItem, sequence: 10, separator: true, }) .addChild("format_number_automatic", ["format", "format_number"], { - name: NumberFormatTerms.Automatic, + ...ACTION_FORMAT.formatNumberAutomaticMenuItem, sequence: 10, separator: true, - action: ACTIONS.FORMAT_AUTOMATIC_ACTION, - isActive: (env) => isAutomaticFormatSelected(env), }) .addChild("format_number_number", ["format", "format_number"], { - name: NumberFormatTerms.Number, - description: "1,000.12", + ...ACTION_FORMAT.formatNumberNumberMenuItem, sequence: 20, - action: ACTIONS.FORMAT_NUMBER_ACTION, - isActive: (env) => isFormatSelected(env, "#,##0.00"), }) .addChild("format_number_percent", ["format", "format_number"], { - name: NumberFormatTerms.Percent, - description: "10.12%", + ...ACTION_FORMAT.formatNumberPercentMenuItem, sequence: 30, separator: true, - action: ACTIONS.FORMAT_PERCENT_ACTION, - isActive: (env) => isFormatSelected(env, "0.00%"), }) .addChild("format_number_currency", ["format", "format_number"], { - name: NumberFormatTerms.Currency, - description: "$1,000.12", + ...ACTION_FORMAT.formatNumberCurrencyMenuItem, sequence: 37, - action: ACTIONS.FORMAT_CURRENCY_ACTION, - isActive: (env) => isFormatSelected(env, "[$$]#,##0.00"), }) .addChild("format_number_currency_rounded", ["format", "format_number"], { - name: NumberFormatTerms.CurrencyRounded, - description: "$1,000", + ...ACTION_FORMAT.formatNumberCurrencyRoundedMenuItem, sequence: 38, - action: ACTIONS.FORMAT_CURRENCY_ROUNDED_ACTION, - isActive: (env) => isFormatSelected(env, "[$$]#,##0"), }) .addChild("format_custom_currency", ["format", "format_number"], { - name: NumberFormatTerms.CustomCurrency, + ...ACTION_FORMAT.formatCustomCurrencyMenuItem, sequence: 39, separator: true, - isVisible: (env) => env.loadCurrencies !== undefined, - action: ACTIONS.OPEN_CUSTOM_CURRENCY_SIDEPANEL_ACTION, }) .addChild("format_number_date", ["format", "format_number"], { - name: NumberFormatTerms.Date, - description: "9/26/2008", + ...ACTION_FORMAT.formatNumberDateMenuItem, sequence: 40, - action: ACTIONS.FORMAT_DATE_ACTION, - isActive: (env) => isFormatSelected(env, "m/d/yyyy"), }) .addChild("format_number_time", ["format", "format_number"], { - name: NumberFormatTerms.Time, - description: "10:43:00 PM", + ...ACTION_FORMAT.formatNumberTimeMenuItem, sequence: 50, - action: ACTIONS.FORMAT_TIME_ACTION, - isActive: (env) => isFormatSelected(env, "hh:mm:ss a"), }) .addChild("format_number_date_time", ["format", "format_number"], { - name: NumberFormatTerms.DateTime, - description: "9/26/2008 22:43:00", + ...ACTION_FORMAT.formatNumberDateTimeMenuItem, sequence: 60, - action: ACTIONS.FORMAT_DATE_TIME_ACTION, - isActive: (env) => isFormatSelected(env, "m/d/yyyy hh:mm:ss"), }) .addChild("format_number_duration", ["format", "format_number"], { - name: NumberFormatTerms.Duration, - description: "27:51:38", + ...ACTION_FORMAT.formatNumberDurationMenuItem, sequence: 70, separator: true, - action: ACTIONS.FORMAT_DURATION_ACTION, - isActive: (env) => isFormatSelected(env, "hhhh:mm:ss"), }) .addChild("format_bold", ["format"], { - name: _lt("Bold"), + ...ACTION_FORMAT.formatBoldMenuItem, sequence: 20, - description: "Ctrl+B", - action: ACTIONS.FORMAT_BOLD_ACTION, - icon: "o-spreadsheet-Icon.BOLD", }) .addChild("format_italic", ["format"], { - name: _lt("Italic"), + ...ACTION_FORMAT.formatItalicMenuItem, sequence: 30, - description: "Ctrl+I", - action: ACTIONS.FORMAT_ITALIC_ACTION, - icon: "o-spreadsheet-Icon.ITALIC", }) .addChild("format_underline", ["format"], { - name: _lt("Underline"), - description: "Ctrl+U", + ...ACTION_FORMAT.formatUnderlineMenuItem, sequence: 40, - action: ACTIONS.FORMAT_UNDERLINE_ACTION, - icon: "o-spreadsheet-Icon.UNDERLINE", }) .addChild("format_strikethrough", ["format"], { - name: _lt("Strikethrough"), + ...ACTION_FORMAT.formatStrikethroughMenuItem, sequence: 50, - action: ACTIONS.FORMAT_STRIKETHROUGH_ACTION, - icon: "o-spreadsheet-Icon.STRIKE", separator: true, }) .addChild("format_font_size", ["format"], { - name: _lt("Font size"), + ...ACTION_FORMAT.formatFontSizeMenuItem, sequence: 60, separator: true, }) .addChild("format_alignment", ["format"], { - name: _lt("Alignment"), + ...ACTION_FORMAT.formatAlignmentMenuItem, sequence: 70, - icon: "o-spreadsheet-Icon.ALIGN_LEFT", }) .addChild("format_alignment_left", ["format", "format_alignment"], { - name: "Left", + ...ACTION_FORMAT.formatAlignmentLeftMenuItem, sequence: 10, - action: (env: SpreadsheetChildEnv) => setStyle(env, { align: "left" }), - icon: "o-spreadsheet-Icon.ALIGN_LEFT", }) .addChild("format_alignment_center", ["format", "format_alignment"], { - name: "Center", + ...ACTION_FORMAT.formatAlignmentCenterMenuItem, sequence: 20, - action: (env: SpreadsheetChildEnv) => setStyle(env, { align: "center" }), - icon: "o-spreadsheet-Icon.ALIGN_CENTER", }) .addChild("format_alignment_right", ["format", "format_alignment"], { - name: "Right", + ...ACTION_FORMAT.formatAlignmentRightMenuItem, sequence: 30, - action: (env: SpreadsheetChildEnv) => setStyle(env, { align: "right" }), - icon: "o-spreadsheet-Icon.ALIGN_RIGHT", separator: true, }) .addChild("format_alignment_top", ["format", "format_alignment"], { - name: "Top", + ...ACTION_FORMAT.formatAlignmentTopMenuItem, sequence: 40, - action: (env: SpreadsheetChildEnv) => setStyle(env, { verticalAlign: "top" }), - icon: "o-spreadsheet-Icon.ALIGN_TOP", }) .addChild("format_alignment_middle", ["format", "format_alignment"], { - name: "Middle", + ...ACTION_FORMAT.formatAlignmentMiddleMenuItem, sequence: 50, - action: (env: SpreadsheetChildEnv) => setStyle(env, { verticalAlign: "middle" }), - icon: "o-spreadsheet-Icon.ALIGN_MIDDLE", }) .addChild("format_alignment_bottom", ["format", "format_alignment"], { - name: "Bottom", + ...ACTION_FORMAT.formatAlignmentBottomMenuItem, sequence: 60, - action: (env: SpreadsheetChildEnv) => setStyle(env, { verticalAlign: "bottom" }), - icon: "o-spreadsheet-Icon.ALIGN_BOTTOM", separator: true, }) .addChild("format_wrapping", ["format"], { - name: _lt("Wrapping"), + ...ACTION_FORMAT.formatWrappingMenuItem, sequence: 80, - icon: "o-spreadsheet-Icon.WRAPPING_OVERFLOW", separator: true, }) .addChild("format_wrapping_overflow", ["format", "format_wrapping"], { - name: _lt("Overflow"), + ...ACTION_FORMAT.formatWrappingOverflowMenuItem, sequence: 10, - action: (env: SpreadsheetChildEnv) => setStyle(env, { wrapping: "overflow" }), - icon: "o-spreadsheet-Icon.WRAPPING_OVERFLOW", }) .addChild("format_wrapping_wrap", ["format", "format_wrapping"], { - name: _lt("Wrap"), + ...ACTION_FORMAT.formatWrappingWrapMenuItem, sequence: 20, - action: (env: SpreadsheetChildEnv) => setStyle(env, { wrapping: "wrap" }), - icon: "o-spreadsheet-Icon.WRAPPING_WRAP", }) .addChild("format_wrapping_clip", ["format", "format_wrapping"], { - name: _lt("Clip"), + ...ACTION_FORMAT.formatWrappingClipMenuItem, sequence: 30, - action: (env: SpreadsheetChildEnv) => setStyle(env, { wrapping: "clip" }), - icon: "o-spreadsheet-Icon.WRAPPING_CLIP", }) .addChild("format_cf", ["format"], { - name: _lt("Conditional formatting"), + ...ACTION_FORMAT.formatCFMenuItem, sequence: 90, - action: ACTIONS.OPEN_CF_SIDEPANEL_ACTION, separator: true, }) .addChild("format_clearFormat", ["format"], { - name: _lt("Clear formatting"), + ...ACTION_FORMAT.clearFormatMenuItem, sequence: 100, - action: ACTIONS.FORMAT_CLEARFORMAT_ACTION, - icon: "o-spreadsheet-Icon.CLEAR_FORMAT", separator: true, }) + + // --------------------------------------------------------------------- + // DATA MENU ITEMS + // --------------------------------------------------------------------- + + .add("data", { + name: _lt("Data"), + sequence: 60, + }) + .addChild("sort_range", ["data"], { + ...ACTION_DATA.sortRangeMenuItem, + sequence: 20, + separator: true, + }) + .addChild("sort_ascending", ["data", "sort_range"], { + ...ACTION_DATA.sortAscendingenuItem, + sequence: 10, + }) + .addChild("sort_descending", ["data", "sort_range"], { + ...ACTION_DATA.sortDescendingMenuItem, + sequence: 20, + }) .addChild("add_data_filter", ["data"], { - name: _lt("Create filter"), + ...ACTION_DATA.addDataFilterMenuItem, sequence: 10, - action: ACTIONS.FILTERS_CREATE_FILTER_TABLE, - isVisible: (env) => !ACTIONS.SELECTION_CONTAINS_FILTER(env), - isEnabled: (env) => ACTIONS.SELECTION_IS_CONTINUOUS(env), - icon: "o-spreadsheet-Icon.FILTER_ICON_INACTIVE", }) .addChild("remove_data_filter", ["data"], { - name: _lt("Remove filter"), + ...ACTION_DATA.removeDataFilterMenuItem, sequence: 10, - action: ACTIONS.FILTERS_REMOVE_FILTER_TABLE, - isVisible: ACTIONS.SELECTION_CONTAINS_FILTER, - icon: "o-spreadsheet-Icon.FILTER_ICON_INACTIVE", - }); - -// Font-sizes -for (let fs of FONT_SIZES) { - topbarMenuRegistry.addChild(`format_font_size_${fs}`, ["format", "format_font_size"], { - name: fs.toString(), - sequence: fs, - action: (env: SpreadsheetChildEnv) => ACTIONS.setStyle(env, { fontSize: fs }), - isActive: (env: SpreadsheetChildEnv) => isFontSizeSelected(env, fs), - }); -} - -function createFormulaFunctionMenuItems(fnNames: string[]): MenuItemSpec[] { - return fnNames.sort().map((fnName, i) => { - return { - name: fnName, - sequence: i * 10, - action: (env) => env.startCellEdition(`=${fnName}(`), - }; }); -} - -function isAutomaticFormatSelected(env: SpreadsheetChildEnv) { - const activeCell = env.model.getters.getActiveCell(); - return !activeCell || !activeCell.format; -} - -function isFormatSelected(env: SpreadsheetChildEnv, format: string): boolean { - const activeCell = env.model.getters.getActiveCell(); - return activeCell && activeCell.format === format; -} - -function isFontSizeSelected(env: SpreadsheetChildEnv, fontSize: number) { - const currentFontSize = env.model.getters.getCurrentStyle().fontSize || DEFAULT_FONT_SIZE; - return currentFontSize === fontSize; -} diff --git a/tests/menu_items_registry.test.ts b/tests/menu_items_registry.test.ts index c6df2afd14..ef8230d09a 100644 --- a/tests/menu_items_registry.test.ts +++ b/tests/menu_items_registry.test.ts @@ -666,7 +666,7 @@ describe("Menu Item actions", () => { test("Format -> font-size", () => { const fontSize = FONT_SIZES[0]; - doAction(["format", "format_font_size", `format_font_size_${fontSize}`], env); + doAction(["format", "format_font_size", `font_size_${fontSize}`], env); expect(dispatch).toHaveBeenCalledWith("SET_FORMATTING", { sheetId: env.model.getters.getActiveSheetId(), target: env.model.getters.getSelectedZones(),