diff --git a/css/mathfield.less b/css/mathfield.less index dd56bcd8b..c46ee61a8 100644 --- a/css/mathfield.less +++ b/css/mathfield.less @@ -430,12 +430,12 @@ menu .ML__base { font-size: 21px; // color: transparent; border: none; - border-radius: 2px; - line-height: 1; + border-radius: 0; + line-height: 21px; text-align: center; - padding: 4px; + padding: 0; margin: 0; -} + } .menu-container-border [part=menu-item] { font-size: 2rem; diff --git a/src/editor/default-menu.ts b/src/editor/default-menu.ts index dd9fb0b92..0e60951eb 100644 --- a/src/editor/default-menu.ts +++ b/src/editor/default-menu.ts @@ -11,6 +11,7 @@ import { Atom } from 'core/atom-class'; import { VARIANT_REPERTOIRE } from 'core/modes-math'; import { contrast } from 'ui/colors/utils'; import { _Mathfield } from 'editor-mathfield/mathfield-private'; +import { _MenuItemState } from 'ui/menu/menu-item'; // Return a string from the selection, if all the atoms are character boxes // (i.e. not fractions, square roots, etc...) @@ -242,24 +243,53 @@ function getColorSubmenu(mf: _Mathfield): MenuItem[] { return result; } +class InsertMatrixMenuItem extends _MenuItemState<{ + row: number; + col: number; +}> { + row: number; + col: number; + constructor(decl, parent, row, col) { + super(decl, parent); + this.row = row; + this.col = col; + } + + set active(value: boolean) { + const cells = this.parentMenu.children as InsertMatrixMenuItem[]; + if (value) { + // Make all the items with a smaller column or row active as well + for (const cell of cells) { + cell.element.classList.toggle( + 'active', + cell.row <= this.row && cell.col <= this.col + ); + } + } else for (const cell of cells) cell.element.classList.remove('active'); + } +} + function getInsertMatrixSubmenu(mf: _Mathfield): MenuItem[] { const result: MenuItem[] = []; - for (let rows = 1; rows <= 5; rows++) { - for (let cols = 1; cols <= 5; cols++) { + for (let row = 1; row <= 5; row++) { + for (let col = 1; col <= 5; col++) { result.push({ + createMenuItem: (decl, parent) => + new InsertMatrixMenuItem(decl, parent, row, col), label: `☐`, + data: { row, col }, onMenuSelect: () => { mf.insert( - `\\begin{pmatrix}${Array(cols) - .fill(Array(rows).fill('#?').join(' & ')) + `\\begin{pmatrix}${Array(col) + .fill(Array(row).fill('#?').join(' & ')) .join('\\\\')}\\end{pmatrix}`, { selectionMode: 'item', } ); }, - }); + } as MenuItem); } } diff --git a/src/public/ui-menu-types.ts b/src/public/ui-menu-types.ts index 2778d683c..2496bfcdc 100644 --- a/src/public/ui-menu-types.ts +++ b/src/public/ui-menu-types.ts @@ -133,7 +133,7 @@ export function isSubmenu(item: MenuItem): item is MenuItemSubmenu { export function isCommand(item: MenuItem): item is MenuItemCommand { return ( ('type' in item && item.type === 'command') || - 'onSelect' in item || + 'onMenuSelect' in item || 'id' in item ); } diff --git a/src/ui/menu/menu-item.ts b/src/ui/menu/menu-item.ts index bce30541e..ddddc50da 100644 --- a/src/ui/menu/menu-item.ts +++ b/src/ui/menu/menu-item.ts @@ -157,8 +157,7 @@ export class _MenuItemState implements MenuItemState { set active(value: boolean) { if (!this.element) return; // The active state is immediate, no need to dirty it - if (value) this.element.classList.add('active'); - else this.element.classList.remove('active'); + this.element.classList.toggle('active', value); } get items(): MenuItemState[] | undefined { diff --git a/src/ui/menu/menu-list.ts b/src/ui/menu/menu-list.ts index b3ca7125f..66016e650 100644 --- a/src/ui/menu/menu-list.ts +++ b/src/ui/menu/menu-list.ts @@ -44,6 +44,10 @@ export class _MenuListState implements MenuListState { this.menuItems = items; } + get children(): MenuItemState[] { + return this._menuItems; + } + /** Setting the menu items will reset this item and * redefine a set of _MenuItem objects */ @@ -54,8 +58,12 @@ export class _MenuListState implements MenuListState { this.parentMenu = parent; items = [...items]; - // Create the _MenuItem objects - this._menuItems = items.map((x) => new _MenuItemState(x, this)); + // Create the _MenuItemState objects + this._menuItems = items.map((x) => + x['createMenuItem'] + ? x['createMenuItem'](x, this) + : new _MenuItemState(x, this) + ); this.hasCheck = undefined; } diff --git a/src/ui/menu/private-types.ts b/src/ui/menu/private-types.ts index e580f98de..139927ca4 100644 --- a/src/ui/menu/private-types.ts +++ b/src/ui/menu/private-types.ts @@ -50,9 +50,11 @@ export interface MenuItemState { /** @internal */ export interface MenuListState { - readonly parentMenu: MenuListState | null; readonly rootMenu: RootMenuState; + readonly parentMenu: MenuListState | null; + readonly children: MenuItemState[]; + readonly element: HTMLElement | null; isSubmenuOpen: boolean;