Excel-style combo navigation (type to filter, arrows to move) and complete tab badges
- editable_combo: every dropdown keytip opens with a filter field focused; typing narrows the list, Up/Down move the highlight (wrapping), Enter or click applies, custom text applies where valid (font size). Fixes arrows and typing in ALT+H FF/FS/N. - Audited all 54 painted ribbon ids against the table: real mismatches fixed (Data Sort/Text-to-Columns/Remove-Duplicates/Subtotal, Review Spelling/ Accessibility/New Comment/Notes, View Zoom/Freeze, Formulas Insert Function/ Name Manager/Define Name/Use-in-Formula/Error Checking/Evaluate, Insert Link/ Comment/Header-Footer/Sparklines, Home Protect Sheet). - keytips.json: dialog kind for real dialog openers; control kind for the 6 chart-type buttons, 7 formula-category buttons, and Orientation (HFQ added, was missing); M-family restructured to Excel semantics (ML/MT/ME/MO/MG/MQ fire directly, MI1 opens Financial) with 14 unreachable children dropped; 383 entries total.
This commit is contained in:
parent
cbd9bb51c6
commit
7ba871c6f2
|
|
@ -64,7 +64,7 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("HBY", Entry::Finish(Action::Command("home.borders"))), // Excel: Line Style; Line Style (submenu TBD)
|
||||
("HC", Entry::Finish(Action::Command("edit.copy"))), // Excel: Copy; fires immediately in Excel; deeper aliases dropped as unreachable
|
||||
("HDC", Entry::Finish(Action::Command("home.deleteColumns"))), // Excel: Delete Columns; Delete Columns
|
||||
("HDD", Entry::Finish(Action::Command("home.deleteCells"))), // Excel: Delete Cells
|
||||
("HDD", Entry::Finish(Action::Dialog("deleteCells"))), // Excel: Delete Cells
|
||||
("HDR", Entry::Finish(Action::Command("home.deleteRows"))), // Excel: Delete Rows; Delete Rows
|
||||
("HDS", Entry::Finish(Action::Command("home.deleteSheet"))), // Excel: Delete Sheet
|
||||
("HEA", Entry::Finish(Action::Command("edit.clearAll"))), // Excel: Clear All
|
||||
|
|
@ -80,7 +80,7 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("HFDO", Entry::Finish(Action::Pending("home.selectObjects"))), // pending; Excel: Select Objects; Select Objects; reserved until the command lands
|
||||
("HFDP", Entry::Finish(Action::Command("arrange.selectionPane"))), // Excel: Selection Pane
|
||||
("HFDR", Entry::Finish(Action::Dialog("find"))), // Excel: Replace; opens Find and Replace
|
||||
("HFDS", Entry::Finish(Action::Command("edit.goToSpecial"))), // Excel: Go To Special
|
||||
("HFDS", Entry::Finish(Action::Dialog("goToSpecial"))), // Excel: Go To Special
|
||||
("HFF", Entry::Finish(Action::Control("home.fontName"))), // Excel: Font Selection; opens the font dropdown
|
||||
("HFG", Entry::Finish(Action::Command("home.increaseFontSize"))), // Excel: Increase Font Size
|
||||
("HFI", Entry::Continue), // Excel: Fill; group level: containment(Fill Up)
|
||||
|
|
@ -90,24 +90,22 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("HFIJ", Entry::Finish(Action::Command("home.justify"))), // Excel: Fill Justify; containment(Justify)
|
||||
("HFIL", Entry::Finish(Action::Command("edit.fillLeft"))), // Excel: Fill Left
|
||||
("HFIR", Entry::Finish(Action::Command("edit.fillRight"))), // Excel: Fill Right
|
||||
("HFIS", Entry::Finish(Action::Command("edit.fillSeries"))), // Excel: Fill Series; containment(Series)
|
||||
("HFIS", Entry::Finish(Action::Dialog("series"))), // Excel: Fill Series; containment(Series)
|
||||
("HFIU", Entry::Finish(Action::Command("edit.fillUp"))), // Excel: Fill Up
|
||||
("HFK", Entry::Finish(Action::Command("home.decreaseFontSize"))), // Excel: Decrease Font Size
|
||||
("HFM", Entry::Finish(Action::Dialog("formatCells"))), // Excel: More Number Formats; More Number Formats opens Format Cells
|
||||
("HFP", Entry::Finish(Action::Command("edit.formatPainter"))), // Excel: Format Painter
|
||||
("HFQ", Entry::Continue), // Excel: Orientation Menu; group level: containment(Orientation)
|
||||
("HFQL", Entry::Finish(Action::Pending("home.angleClockwise"))), // pending; Excel: Angle Clockwise; Angle Clockwise; reserved until the command lands
|
||||
("HFQO", Entry::Finish(Action::Pending("home.angleCounterclockwise"))), // pending; Excel: Angle Counterclockwise; Angle Counterclockwise; reserved until the command lands
|
||||
("HFS", Entry::Finish(Action::Control("home.fontSize"))), // Excel: Font Size; opens the font-size dropdown
|
||||
("HH", Entry::Finish(Action::Control("home.fillColor"))), // Excel: Fill Color; opens the fill-color palette
|
||||
("HIC", Entry::Finish(Action::Command("home.insertColumns"))), // Excel: Insert Columns; Insert Columns
|
||||
("HIE", Entry::Finish(Action::Command("home.insertCells"))), // Excel: Insert Copied Cells; Insert Cells (copied cells TBD)
|
||||
("HII", Entry::Finish(Action::Command("home.insertCells"))), // Excel: Insert Cells
|
||||
("HIR", Entry::Finish(Action::Command("home.insertRows"))), // Excel: Insert Rows; Insert Rows
|
||||
("HIS", Entry::Finish(Action::Command("home.insertSheet"))), // Excel: Insert Sheet
|
||||
("HJ", Entry::Continue), // Excel: Cell Styles; group level:
|
||||
("HJN", Entry::Finish(Action::Command("home.newCellStyle"))), // Excel: New Cell Style
|
||||
("HK", Entry::Finish(Action::Command("home.comma"))), // Excel: Comma Style
|
||||
("HFQ", Entry::Finish(Action::Control("home.orientation"))), // Excel: Orientation Menu; group level: containment(Orientation)
|
||||
("HFS", Entry::Finish(Action::Control("home.fontSize"))), // Excel: Font Size; opens the font-size dropdown
|
||||
("HH", Entry::Finish(Action::Control("home.fillColor"))), // Excel: Fill Color; opens the fill-color palette
|
||||
("HIC", Entry::Finish(Action::Command("home.insertColumns"))), // Excel: Insert Columns; Insert Columns
|
||||
("HIE", Entry::Finish(Action::Dialog("insertCells"))), // Excel: Insert Copied Cells; Insert Cells (copied cells TBD)
|
||||
("HII", Entry::Finish(Action::Dialog("insertCells"))), // Excel: Insert Cells
|
||||
("HIR", Entry::Finish(Action::Command("home.insertRows"))), // Excel: Insert Rows; Insert Rows
|
||||
("HIS", Entry::Finish(Action::Command("home.insertSheet"))), // Excel: Insert Sheet
|
||||
("HJ", Entry::Continue), // Excel: Cell Styles; group level:
|
||||
("HJN", Entry::Finish(Action::Command("home.newCellStyle"))), // Excel: New Cell Style
|
||||
("HK", Entry::Finish(Action::Command("home.comma"))), // Excel: Comma Style
|
||||
("HL", Entry::Continue), // Excel: Conditional Formatting; group level: containment(Conditional Formatting)
|
||||
("HLC", Entry::Continue), // Excel: Clear Rules Menu; group level: containment(Clear Rules)
|
||||
("HLCE", Entry::Finish(Action::Command("home.clearRules"))), // Excel: Clear Rules From Sheet; containment(Clear Rules)
|
||||
|
|
@ -130,7 +128,7 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("HOH", Entry::Finish(Action::Dialog("rowHeight"))), // Excel: Row Height
|
||||
("HOL", Entry::Finish(Action::Command("home.lockCell"))), // Excel: Lock Cell; containment(Lock Cell)
|
||||
("HOM", Entry::Finish(Action::Dialog("moveSheet"))), // Excel: Move or Copy Sheet
|
||||
("HOP", Entry::Finish(Action::Command("review.protectSheet"))), // Excel: Protect Sheet
|
||||
("HOP", Entry::Finish(Action::Dialog("protectSheet"))), // Excel: Protect Sheet
|
||||
("HOR", Entry::Finish(Action::Dialog("renameSheet"))), // Excel: Rename Sheet
|
||||
("HOT", Entry::Finish(Action::Command("sheet.tabColor"))), // Excel: Tab Color
|
||||
("HOUC", Entry::Finish(Action::Command("home.hideColumns"))), // Excel: Hide Columns
|
||||
|
|
@ -159,33 +157,33 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("HW", Entry::Continue), // Excel: Wrap Text Menu; group level: containment(Wrap Text)
|
||||
("HWW", Entry::Finish(Action::Command("home.wrapText"))), // Excel: Wrap Text
|
||||
("HX", Entry::Finish(Action::Command("edit.cut"))), // Excel: Cut
|
||||
("NC1", Entry::Finish(Action::Command("insert.chart"))), // Excel: Column Chart; Column chart (kind TBD)
|
||||
("NC1", Entry::Finish(Action::Control("insert.chart.column"))), // Excel: Column Chart; Column chart (kind TBD)
|
||||
("NC2", Entry::Finish(Action::Command("review.newComment"))), // Excel: New Comment
|
||||
("NCM", Entry::Finish(Action::Command("review.newComment"))), // Excel: Excel: New Comment (modern)
|
||||
("NCM", Entry::Finish(Action::Dialog("comment"))), // Excel: Excel: New Comment (modern)
|
||||
("NCB", Entry::Finish(Action::Command("insert.checkbox"))), // Excel: Checkbox
|
||||
("ND", Entry::Finish(Action::Command("insert.chart"))), // Excel: Scatter Chart; Scatter (kind TBD)
|
||||
("ND", Entry::Finish(Action::Control("insert.chart.scatter"))), // Excel: Scatter Chart; Scatter (kind TBD)
|
||||
("NE", Entry::Finish(Action::Pending("insert.equation"))), // pending; Excel: Equations; Equations; reserved until the command lands
|
||||
("NF", Entry::Continue), // Excel: Online Pictures; group level: containment(Picture)
|
||||
("NFP", Entry::Continue), // Excel: From Picture Menu; group level: containment(Picture)
|
||||
("NFPF", Entry::Finish(Action::Command("insert.picture"))), // Excel: Picture From File; containment(Picture)
|
||||
("NH1", Entry::Finish(Action::Command("pageLayout.headerFooter"))), // Excel: Header & Footer
|
||||
("NH1", Entry::Finish(Action::Dialog("headerFooter"))), // Excel: Header & Footer
|
||||
("NHF", Entry::Finish(Action::Command("pageLayout.headerFooter"))), // Excel: Header & Footer
|
||||
("NHI", Entry::Finish(Action::Command("insert.chart"))), // Excel: Hierarchy Chart; Hierarchy (kind TBD)
|
||||
("NHI", Entry::Finish(Action::Control("insert.chart.hierarchy"))), // Excel: Hierarchy Chart; Hierarchy (kind TBD)
|
||||
("NI1", Entry::Finish(Action::Command("insert.chart"))), // Excel: Waterfall Chart; Waterfall (kind TBD)
|
||||
("NI2", Entry::Finish(Action::Command("insert.link"))), // Excel: Link
|
||||
("NI2", Entry::Finish(Action::Dialog("insertLink"))), // Excel: Link
|
||||
("NJ", Entry::Finish(Action::Pending("insert.object"))), // pending; Excel: Object; insert.object missing; reserved until the command lands
|
||||
("NM1T", Entry::Finish(Action::Command("insert.picture"))), // Excel: SmartArt Picture; containment(Picture)
|
||||
("NM2", Entry::Finish(Action::Command("insert.chart"))), // Excel: Map Chart; Map (kind TBD)
|
||||
("NN1", Entry::Finish(Action::Command("insert.chart"))), // Excel: Line Chart; Line chart (kind TBD)
|
||||
("NN1", Entry::Finish(Action::Control("insert.chart.line"))), // Excel: Line Chart; Line chart (kind TBD)
|
||||
("NNS", Entry::Finish(Action::Command("insert.icons"))), // Excel: Icons
|
||||
("NP", Entry::Continue), // Excel: Picture; group level:
|
||||
("NPB", Entry::Finish(Action::Command("insert.picture"))), // Excel: Picture from File; containment(Picture)
|
||||
("NPF", Entry::Finish(Action::Command("insert.picture"))), // Excel: Place in Cell; Picture in cell (source TBD)
|
||||
("NPI", Entry::Finish(Action::Command("insert.picture"))), // Excel: Place in Cell Menu; Picture in cell (source TBD)
|
||||
("NPO", Entry::Finish(Action::Command("insert.picture"))), // Excel: Place over Cells Menu; Picture over cells (source TBD)
|
||||
("NQ", Entry::Finish(Action::Command("insert.chart"))), // Excel: Pie Chart; Pie (kind TBD)
|
||||
("NQ", Entry::Finish(Action::Control("insert.chart.pie"))), // Excel: Pie Chart; Pie (kind TBD)
|
||||
("NR", Entry::Finish(Action::Command("insert.recommendedCharts"))), // Excel: Recommended Charts
|
||||
("NSA", Entry::Finish(Action::Command("insert.chart"))), // Excel: Statistical Chart; Statistical chart (kind TBD)
|
||||
("NSA", Entry::Finish(Action::Control("insert.chart.statistic"))), // Excel: Statistical Chart; Statistical chart (kind TBD)
|
||||
("NSC", Entry::Finish(Action::Pending("insert.screenshot"))), // pending; Excel: Screenshot Menu; Screenshot; reserved until the command lands
|
||||
("NSD", Entry::Finish(Action::Command("insert.chart"))), // Excel: Combo Chart; Combo (kind TBD)
|
||||
("NSF", Entry::Finish(Action::Pending("insert.slicer"))), // pending; Excel: Slicer; insert.slicer missing (gap #8); reserved until the command lands
|
||||
|
|
@ -219,7 +217,7 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("PPH", Entry::Finish(Action::Command("pageLayout.printHeadings"))), // Excel: Print Headings
|
||||
("PR", Entry::Continue), // Excel: Print Area; group level:
|
||||
("PRS", Entry::Finish(Action::Command("pageLayout.printArea"))), // Excel: Set Print Area
|
||||
("PSP", Entry::Finish(Action::Command("pageLayout.pageSetup"))), // Excel: Page Setup
|
||||
("PSP", Entry::Finish(Action::Dialog("pageSetup"))), // Excel: Page Setup
|
||||
("PSZ", Entry::Finish(Action::Command("pageLayout.size"))), // Excel: Size
|
||||
("PTC", Entry::Finish(Action::Command("pageLayout.themeColors"))), // Excel: Theme Colors; containment(Colors)
|
||||
("PTE", Entry::Finish(Action::Command("pageLayout.themeEffects"))), // Excel: Theme Effects; containment(Effects)
|
||||
|
|
@ -234,55 +232,41 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("MB", Entry::Finish(Action::Command("formulas.calculateNow"))), // Excel: Calculate Now
|
||||
("MC", Entry::Finish(Action::Command("formulas.createFromSelection"))), // Excel: Create From Selection
|
||||
("MD", Entry::Finish(Action::Command("formulas.traceDependents"))), // Excel: Trace Dependents
|
||||
("ME", Entry::Continue), // Excel: Date & Time Menu; group level: containment(Date & Time)
|
||||
("MEF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Date & Time - Insert Function; containment(Insert Function)
|
||||
("MF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Insert Function
|
||||
("MG", Entry::Continue), // Excel: Math & Trig Menu; group level: containment(Math & Trig)
|
||||
("MGF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Math & Trig - Insert Function; containment(Insert Function)
|
||||
("ME", Entry::Finish(Action::Control("formulas.dateTime"))), // Excel: Date & Time Menu; group level: containment(Date & Time)
|
||||
("MF", Entry::Finish(Action::Dialog("insertFunction"))), // Excel: Insert Function
|
||||
("MG", Entry::Finish(Action::Control("formulas.mathTrig"))), // Excel: Math & Trig Menu; group level: containment(Math & Trig)
|
||||
("MH", Entry::Finish(Action::Command("formulas.showFormulas"))), // Excel: Show Formulas
|
||||
("MI", Entry::Continue), // Excel: Financial Menu; group level: containment(Financial)
|
||||
("MI1", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Excel: Financial; first item of the dropdown
|
||||
("MIF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Financial - Insert Function; containment(Insert Function)
|
||||
("MI1", Entry::Finish(Action::Control("formulas.financial"))), // Excel: Excel: Financial; first item of the dropdown
|
||||
("MJ", Entry::Finish(Action::Command("formulas.calculateSheet"))), // Excel: Calculate Sheet
|
||||
("MK", Entry::Continue), // Excel: Error Checking Menu; group level: containment(Error Checking)
|
||||
("MKK", Entry::Finish(Action::Command("formulas.errorChecking"))), // Excel: Error Checking
|
||||
("ML", Entry::Continue), // Excel: Logical Menu; group level: containment(Logical)
|
||||
("MLF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Logical - Insert Function; containment(Insert Function)
|
||||
("MM", Entry::Finish(Action::Command("formulas.defineName"))), // Excel: Define Name
|
||||
("MN", Entry::Finish(Action::Command("formulas.nameManager"))), // Excel: Name Manager
|
||||
("MO", Entry::Continue), // Excel: Lookup & Reference Menu; group level: containment(Lookup & Reference)
|
||||
("MOF", Entry::Finish(Action::Command("formulas.lookupReference"))), // Excel: Lookup & Reference - Insert Function; containment(Lookup & Reference)
|
||||
("MP", Entry::Finish(Action::Command("formulas.tracePrecedents"))), // Excel: Trace Precedents
|
||||
("MQ", Entry::Continue), // Excel: More Functions Menu; group level: containment(More Functions)
|
||||
("MQCF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Cube - Insert Function; containment(Insert Function)
|
||||
("MQEF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Engineering - Insert Function; containment(Insert Function)
|
||||
("MQIF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Information - Insert Function; containment(Insert Function)
|
||||
("MQOF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Compatibility - Insert Function; containment(Insert Function)
|
||||
("MQSF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Statistical - Insert Function; containment(Insert Function)
|
||||
("MQWF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Web - Insert Function; containment(Insert Function)
|
||||
("MR", Entry::Continue), // Excel: Recently Used Menu; group level: containment(Recently Used)
|
||||
("MRF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Recently Used - Insert Function; containment(Insert Function)
|
||||
("MS", Entry::Continue), // Excel: Use in Formula Menu; group level: containment(Use in Formula)
|
||||
("MSP", Entry::Finish(Action::Pending("formulas.pasteName"))), // pending; Excel: Paste Names; reserved until the command lands
|
||||
("MT", Entry::Continue), // Excel: Text Menu; group level: containment(Text)
|
||||
("MTF", Entry::Finish(Action::Command("formulas.insertFunction"))), // Excel: Text - Insert Function; containment(Insert Function)
|
||||
("MU", Entry::Continue), // Excel: AutoSum Menu; group level:
|
||||
("MUA", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Average; AutoSum: Average (variant TBD)
|
||||
("MUC", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Count Numbers; AutoSum: Count (variant TBD)
|
||||
("MUF", Entry::Finish(Action::Command("formulas.moreFunctions"))), // Excel: More Functions (AutoSum); containment(More Functions)
|
||||
("MUI", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Min; AutoSum: Min (variant TBD)
|
||||
("MUM", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Max; AutoSum: Max (variant TBD)
|
||||
("MUS", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Sum
|
||||
("MV", Entry::Finish(Action::Dialog("evaluateFormula"))), // Excel: Evaluate Formula
|
||||
("MW", Entry::Finish(Action::Command("formulas.watchWindow"))), // Excel: Watch Window
|
||||
("MX", Entry::Continue), // Excel: Calculation Options Menu; group level: containment(Calculation Options)
|
||||
("MKK", Entry::Finish(Action::Dialog("errorChecking"))), // Excel: Error Checking
|
||||
("ML", Entry::Finish(Action::Control("formulas.logical"))), // Excel: Logical Menu; group level: containment(Logical)
|
||||
("MM", Entry::Finish(Action::Dialog("defineName"))), // Excel: Define Name
|
||||
("MN", Entry::Finish(Action::Dialog("nameManager"))), // Excel: Name Manager
|
||||
("MO", Entry::Finish(Action::Control("formulas.lookup"))), // Excel: Lookup & Reference Menu; group level: containment(Lookup & Reference)
|
||||
("MP", Entry::Finish(Action::Command("formulas.tracePrecedents"))), // Excel: Trace Precedents
|
||||
("MQ", Entry::Finish(Action::Control("formulas.moreFunctions"))), // Excel: More Functions Menu; group level: containment(More Functions)
|
||||
("MS", Entry::Continue), // Excel: Use in Formula Menu; group level: containment(Use in Formula)
|
||||
("MSP", Entry::Finish(Action::Pending("formulas.pasteName"))), // pending; Excel: Paste Names; reserved until the command lands
|
||||
("MT", Entry::Finish(Action::Control("formulas.text"))), // Excel: Text Menu; group level: containment(Text)
|
||||
("MU", Entry::Continue), // Excel: AutoSum Menu; group level:
|
||||
("MUA", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Average; AutoSum: Average (variant TBD)
|
||||
("MUC", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Count Numbers; AutoSum: Count (variant TBD)
|
||||
("MUF", Entry::Finish(Action::Command("formulas.moreFunctions"))), // Excel: More Functions (AutoSum); containment(More Functions)
|
||||
("MUI", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Min; AutoSum: Min (variant TBD)
|
||||
("MUM", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Max; AutoSum: Max (variant TBD)
|
||||
("MUS", Entry::Finish(Action::Command("formulas.autoSum"))), // Excel: Sum
|
||||
("MV", Entry::Finish(Action::Dialog("evaluateFormula"))), // Excel: Evaluate Formula
|
||||
("MW", Entry::Finish(Action::Command("formulas.watchWindow"))), // Excel: Watch Window
|
||||
("MX", Entry::Continue), // Excel: Calculation Options Menu; group level: containment(Calculation Options)
|
||||
("MXA", Entry::Finish(Action::Command("formulas.calculationOptions"))), // Excel: Automatic Calculation; Calculation options: Automatic
|
||||
("MXM", Entry::Finish(Action::Command("formulas.calculationOptions"))), // Excel: Manual Calculation; Calculation options: Manual
|
||||
("MXP", Entry::Finish(Action::Command("formulas.calculationOptions"))), // Excel: Partial Calculation; Calculation options: Partial
|
||||
("AB", Entry::Finish(Action::Command("data.subtotal"))), // Excel: Subtotal
|
||||
("AB", Entry::Finish(Action::Dialog("subtotal"))), // Excel: Subtotal
|
||||
("AC", Entry::Finish(Action::Command("data.clearFilter"))), // Excel: Clear Filter
|
||||
("AD", Entry::Finish(Action::Command("data.consolidate"))), // Excel: Consolidate
|
||||
("AE", Entry::Finish(Action::Command("data.textToColumns"))), // Excel: Text to Columns
|
||||
("AE", Entry::Finish(Action::Dialog("textToColumns"))), // Excel: Text to Columns
|
||||
("AF1", Entry::Continue), // Excel: Data from Picture Menu; group level: feature gap; reserved until the command lands
|
||||
("AF1C", Entry::Finish(Action::Command("insert.picture"))), // Excel: Picture from Clipboard (source TBD)
|
||||
("AF1P", Entry::Finish(Action::Command("insert.picture"))), // Excel: Picture from File (source TBD)
|
||||
|
|
@ -299,7 +283,7 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("AH", Entry::Finish(Action::Command("data.hideDetail"))), // Excel: Hide Detail
|
||||
("AJ", Entry::Finish(Action::Command("data.showDetail"))), // Excel: Show Detail
|
||||
("AK", Entry::Finish(Action::Command("data.queriesConnections"))), // Excel: Edit Links; Edit Links (Queries & Connections);
|
||||
("AM", Entry::Finish(Action::Command("data.removeDuplicates"))), // Excel: Remove Duplicates
|
||||
("AM", Entry::Finish(Action::Dialog("removeDuplicates"))), // Excel: Remove Duplicates
|
||||
("AO", Entry::Finish(Action::Command("data.queriesConnections"))), // Excel: Queries & Connections
|
||||
("AP1", Entry::Finish(Action::Command("file.properties"))), // Excel: Properties
|
||||
("APN", Entry::Continue), // Excel: Get Data (Power Query) Menu; group level: Power Query variants = GAP
|
||||
|
|
@ -322,7 +306,7 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("ARS", Entry::Finish(Action::Pending("data.refreshStatus"))), // pending; Excel: Refresh Status; gap #12; reserved until the command lands
|
||||
("ASA", Entry::Finish(Action::Command("data.sortAscending"))), // Excel: Sort A to Z
|
||||
("ASD", Entry::Finish(Action::Command("data.sortDescending"))), // Excel: Sort Z to A
|
||||
("ASS", Entry::Finish(Action::Command("data.sort"))), // Excel: Sort
|
||||
("ASS", Entry::Finish(Action::Dialog("sort"))), // Excel: Sort
|
||||
("AT", Entry::Finish(Action::Command("data.filter"))), // Excel: Filter
|
||||
("AU", Entry::Continue), // Excel: Ungroup Menu; group level: containment(Ungroup)
|
||||
("AUC", Entry::Finish(Action::Pending("data.clearOutline"))), // pending; Excel: Clear Outline; feature gap; reserved until the command lands
|
||||
|
|
@ -337,18 +321,18 @@ pub const SEQUENCES: &[(&str, Entry)] = &[
|
|||
("AWT", Entry::Finish(Action::Command("data.dataTable"))), // Excel: Data Table
|
||||
("AX", Entry::Finish(Action::Pending("data.existingConnections"))), // pending; Excel: Existing Connections; gap #12; reserved until the command lands
|
||||
("AY", Entry::Finish(Action::Command("data.reapply"))), // Excel: Reapply Filter; containment(Reapply)
|
||||
("RA1", Entry::Finish(Action::Command("review.checkAccessibility"))), // Excel: Check Accessibility
|
||||
("RA1", Entry::Finish(Action::Dialog("accessibility"))), // Excel: Check Accessibility
|
||||
("RA2", Entry::Finish(Action::Pending("review.showComments"))), // pending; Excel: Show All Comments; Show All Comments; reserved until the command lands
|
||||
("RC", Entry::Finish(Action::Command("review.newComment"))), // Excel: New Comment
|
||||
("RC", Entry::Finish(Action::Dialog("comment"))), // Excel: New Comment
|
||||
("RD", Entry::Finish(Action::Command("review.deleteComment"))), // Excel: Delete Comment
|
||||
("RG", Entry::Finish(Action::Pending("review.showChanges"))), // pending; Excel: Track Changes; reserved until the command lands
|
||||
("RL", Entry::Finish(Action::Pending("review.translate"))), // pending; Excel: Translate; feature gap; reserved until the command lands
|
||||
("RN", Entry::Finish(Action::Pending("review.nextComment"))), // pending; Excel: Next Comment; Next Comment; reserved until the command lands
|
||||
("RO", Entry::Finish(Action::Command("review.protectWorkbook"))), // Excel: Protect and Share Workbook
|
||||
("RPS", Entry::Finish(Action::Command("review.protectSheet"))), // Excel: Protect Sheet
|
||||
("RPS", Entry::Finish(Action::Dialog("protectSheet"))), // Excel: Protect Sheet
|
||||
("RPW", Entry::Finish(Action::Command("review.protectWorkbook"))), // Excel: Protect Workbook
|
||||
("RRS", Entry::Finish(Action::Pending("review.smartLookup"))), // pending; Excel: Smart Lookup; feature gap; reserved until the command lands
|
||||
("RS", Entry::Finish(Action::Command("review.spelling"))), // Excel: Spelling
|
||||
("RS", Entry::Finish(Action::Dialog("spelling"))), // Excel: Spelling
|
||||
("RTN", Entry::Finish(Action::Command("review.newNote"))), // Excel: New Note
|
||||
("RV", Entry::Finish(Action::Pending("review.previousComment"))), // pending; Excel: Previous Comment; Previous Comment; reserved until the command lands
|
||||
("RW", Entry::Finish(Action::Pending("review.shareWorkbook"))), // pending; Excel: Share Workbook; reserved until the command lands
|
||||
|
|
|
|||
|
|
@ -389,8 +389,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "HDD",
|
||||
"kind": "command",
|
||||
"target": "home.deleteCells",
|
||||
"kind": "dialog",
|
||||
"target": "deleteCells",
|
||||
"excel": "Delete Cells",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -502,8 +502,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "HFDS",
|
||||
"kind": "command",
|
||||
"target": "edit.goToSpecial",
|
||||
"kind": "dialog",
|
||||
"target": "goToSpecial",
|
||||
"excel": "Go To Special",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -572,8 +572,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "HFIS",
|
||||
"kind": "command",
|
||||
"target": "edit.fillSeries",
|
||||
"kind": "dialog",
|
||||
"target": "series",
|
||||
"excel": "Fill Series",
|
||||
"note": "containment(Series)"
|
||||
},
|
||||
|
|
@ -607,25 +607,10 @@
|
|||
},
|
||||
{
|
||||
"seq": "HFQ",
|
||||
"kind": "continue",
|
||||
"kind": "control",
|
||||
"excel": "Orientation Menu",
|
||||
"note": "group level: containment(Orientation)"
|
||||
},
|
||||
{
|
||||
"seq": "HFQL",
|
||||
"kind": "command",
|
||||
"target": "home.angleClockwise",
|
||||
"pending": true,
|
||||
"excel": "Angle Clockwise",
|
||||
"note": "Angle Clockwise; reserved until the command lands"
|
||||
},
|
||||
{
|
||||
"seq": "HFQO",
|
||||
"kind": "command",
|
||||
"target": "home.angleCounterclockwise",
|
||||
"pending": true,
|
||||
"excel": "Angle Counterclockwise",
|
||||
"note": "Angle Counterclockwise; reserved until the command lands"
|
||||
"note": "group level: containment(Orientation)",
|
||||
"target": "home.orientation"
|
||||
},
|
||||
{
|
||||
"seq": "HFS",
|
||||
|
|
@ -650,15 +635,15 @@
|
|||
},
|
||||
{
|
||||
"seq": "HIE",
|
||||
"kind": "command",
|
||||
"target": "home.insertCells",
|
||||
"kind": "dialog",
|
||||
"target": "insertCells",
|
||||
"excel": "Insert Copied Cells",
|
||||
"note": "Insert Cells (copied cells TBD)"
|
||||
},
|
||||
{
|
||||
"seq": "HII",
|
||||
"kind": "command",
|
||||
"target": "home.insertCells",
|
||||
"kind": "dialog",
|
||||
"target": "insertCells",
|
||||
"excel": "Insert Cells",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -849,8 +834,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "HOP",
|
||||
"kind": "command",
|
||||
"target": "review.protectSheet",
|
||||
"kind": "dialog",
|
||||
"target": "protectSheet",
|
||||
"excel": "Protect Sheet",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -1047,8 +1032,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "NC1",
|
||||
"kind": "command",
|
||||
"target": "insert.chart",
|
||||
"kind": "control",
|
||||
"target": "insert.chart.column",
|
||||
"excel": "Column Chart",
|
||||
"note": "Column chart (kind TBD)"
|
||||
},
|
||||
|
|
@ -1061,8 +1046,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "NCM",
|
||||
"kind": "command",
|
||||
"target": "review.newComment",
|
||||
"kind": "dialog",
|
||||
"target": "comment",
|
||||
"excel": "Excel: New Comment (modern)"
|
||||
},
|
||||
{
|
||||
|
|
@ -1074,8 +1059,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "ND",
|
||||
"kind": "command",
|
||||
"target": "insert.chart",
|
||||
"kind": "control",
|
||||
"target": "insert.chart.scatter",
|
||||
"excel": "Scatter Chart",
|
||||
"note": "Scatter (kind TBD)"
|
||||
},
|
||||
|
|
@ -1108,8 +1093,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "NH1",
|
||||
"kind": "command",
|
||||
"target": "pageLayout.headerFooter",
|
||||
"kind": "dialog",
|
||||
"target": "headerFooter",
|
||||
"excel": "Header & Footer",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -1122,8 +1107,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "NHI",
|
||||
"kind": "command",
|
||||
"target": "insert.chart",
|
||||
"kind": "control",
|
||||
"target": "insert.chart.hierarchy",
|
||||
"excel": "Hierarchy Chart",
|
||||
"note": "Hierarchy (kind TBD)"
|
||||
},
|
||||
|
|
@ -1136,8 +1121,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "NI2",
|
||||
"kind": "command",
|
||||
"target": "insert.link",
|
||||
"kind": "dialog",
|
||||
"target": "insertLink",
|
||||
"excel": "Link",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -1165,8 +1150,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "NN1",
|
||||
"kind": "command",
|
||||
"target": "insert.chart",
|
||||
"kind": "control",
|
||||
"target": "insert.chart.line",
|
||||
"excel": "Line Chart",
|
||||
"note": "Line chart (kind TBD)"
|
||||
},
|
||||
|
|
@ -1213,8 +1198,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "NQ",
|
||||
"kind": "command",
|
||||
"target": "insert.chart",
|
||||
"kind": "control",
|
||||
"target": "insert.chart.pie",
|
||||
"excel": "Pie Chart",
|
||||
"note": "Pie (kind TBD)"
|
||||
},
|
||||
|
|
@ -1227,8 +1212,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "NSA",
|
||||
"kind": "command",
|
||||
"target": "insert.chart",
|
||||
"kind": "control",
|
||||
"target": "insert.chart.statistic",
|
||||
"excel": "Statistical Chart",
|
||||
"note": "Statistical chart (kind TBD)"
|
||||
},
|
||||
|
|
@ -1464,8 +1449,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "PSP",
|
||||
"kind": "command",
|
||||
"target": "pageLayout.pageSetup",
|
||||
"kind": "dialog",
|
||||
"target": "pageSetup",
|
||||
"excel": "Page Setup",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -1568,36 +1553,24 @@
|
|||
},
|
||||
{
|
||||
"seq": "ME",
|
||||
"kind": "continue",
|
||||
"kind": "control",
|
||||
"excel": "Date & Time Menu",
|
||||
"note": "group level: containment(Date & Time)"
|
||||
},
|
||||
{
|
||||
"seq": "MEF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Date & Time - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
"note": "group level: containment(Date & Time)",
|
||||
"target": "formulas.dateTime"
|
||||
},
|
||||
{
|
||||
"seq": "MF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"kind": "dialog",
|
||||
"target": "insertFunction",
|
||||
"excel": "Insert Function",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"seq": "MG",
|
||||
"kind": "continue",
|
||||
"kind": "control",
|
||||
"excel": "Math & Trig Menu",
|
||||
"note": "group level: containment(Math & Trig)"
|
||||
},
|
||||
{
|
||||
"seq": "MGF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Math & Trig - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
"note": "group level: containment(Math & Trig)",
|
||||
"target": "formulas.mathTrig"
|
||||
},
|
||||
{
|
||||
"seq": "MH",
|
||||
|
|
@ -1614,17 +1587,10 @@
|
|||
},
|
||||
{
|
||||
"seq": "MI1",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"kind": "control",
|
||||
"target": "formulas.financial",
|
||||
"excel": "Excel: Financial; first item of the dropdown"
|
||||
},
|
||||
{
|
||||
"seq": "MIF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Financial - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
},
|
||||
{
|
||||
"seq": "MJ",
|
||||
"kind": "command",
|
||||
|
|
@ -1640,50 +1606,38 @@
|
|||
},
|
||||
{
|
||||
"seq": "MKK",
|
||||
"kind": "command",
|
||||
"target": "formulas.errorChecking",
|
||||
"kind": "dialog",
|
||||
"target": "errorChecking",
|
||||
"excel": "Error Checking",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"seq": "ML",
|
||||
"kind": "continue",
|
||||
"kind": "control",
|
||||
"excel": "Logical Menu",
|
||||
"note": "group level: containment(Logical)"
|
||||
},
|
||||
{
|
||||
"seq": "MLF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Logical - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
"note": "group level: containment(Logical)",
|
||||
"target": "formulas.logical"
|
||||
},
|
||||
{
|
||||
"seq": "MM",
|
||||
"kind": "command",
|
||||
"target": "formulas.defineName",
|
||||
"kind": "dialog",
|
||||
"target": "defineName",
|
||||
"excel": "Define Name",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"seq": "MN",
|
||||
"kind": "command",
|
||||
"target": "formulas.nameManager",
|
||||
"kind": "dialog",
|
||||
"target": "nameManager",
|
||||
"excel": "Name Manager",
|
||||
"note": ""
|
||||
},
|
||||
{
|
||||
"seq": "MO",
|
||||
"kind": "continue",
|
||||
"kind": "control",
|
||||
"excel": "Lookup & Reference Menu",
|
||||
"note": "group level: containment(Lookup & Reference)"
|
||||
},
|
||||
{
|
||||
"seq": "MOF",
|
||||
"kind": "command",
|
||||
"target": "formulas.lookupReference",
|
||||
"excel": "Lookup & Reference - Insert Function",
|
||||
"note": "containment(Lookup & Reference)"
|
||||
"note": "group level: containment(Lookup & Reference)",
|
||||
"target": "formulas.lookup"
|
||||
},
|
||||
{
|
||||
"seq": "MP",
|
||||
|
|
@ -1694,64 +1648,10 @@
|
|||
},
|
||||
{
|
||||
"seq": "MQ",
|
||||
"kind": "continue",
|
||||
"kind": "control",
|
||||
"excel": "More Functions Menu",
|
||||
"note": "group level: containment(More Functions)"
|
||||
},
|
||||
{
|
||||
"seq": "MQCF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Cube - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
},
|
||||
{
|
||||
"seq": "MQEF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Engineering - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
},
|
||||
{
|
||||
"seq": "MQIF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Information - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
},
|
||||
{
|
||||
"seq": "MQOF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Compatibility - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
},
|
||||
{
|
||||
"seq": "MQSF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Statistical - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
},
|
||||
{
|
||||
"seq": "MQWF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Web - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
},
|
||||
{
|
||||
"seq": "MR",
|
||||
"kind": "continue",
|
||||
"excel": "Recently Used Menu",
|
||||
"note": "group level: containment(Recently Used)"
|
||||
},
|
||||
{
|
||||
"seq": "MRF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Recently Used - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
"note": "group level: containment(More Functions)",
|
||||
"target": "formulas.moreFunctions"
|
||||
},
|
||||
{
|
||||
"seq": "MS",
|
||||
|
|
@ -1769,16 +1669,10 @@
|
|||
},
|
||||
{
|
||||
"seq": "MT",
|
||||
"kind": "continue",
|
||||
"kind": "control",
|
||||
"excel": "Text Menu",
|
||||
"note": "group level: containment(Text)"
|
||||
},
|
||||
{
|
||||
"seq": "MTF",
|
||||
"kind": "command",
|
||||
"target": "formulas.insertFunction",
|
||||
"excel": "Text - Insert Function",
|
||||
"note": "containment(Insert Function)"
|
||||
"note": "group level: containment(Text)",
|
||||
"target": "formulas.text"
|
||||
},
|
||||
{
|
||||
"seq": "MU",
|
||||
|
|
@ -1871,8 +1765,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "AB",
|
||||
"kind": "command",
|
||||
"target": "data.subtotal",
|
||||
"kind": "dialog",
|
||||
"target": "subtotal",
|
||||
"excel": "Subtotal",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -1892,8 +1786,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "AE",
|
||||
"kind": "command",
|
||||
"target": "data.textToColumns",
|
||||
"kind": "dialog",
|
||||
"target": "textToColumns",
|
||||
"excel": "Text to Columns",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -2014,8 +1908,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "AM",
|
||||
"kind": "command",
|
||||
"target": "data.removeDuplicates",
|
||||
"kind": "dialog",
|
||||
"target": "removeDuplicates",
|
||||
"excel": "Remove Duplicates",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -2183,8 +2077,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "ASS",
|
||||
"kind": "command",
|
||||
"target": "data.sort",
|
||||
"kind": "dialog",
|
||||
"target": "sort",
|
||||
"excel": "Sort",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -2287,8 +2181,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "RA1",
|
||||
"kind": "command",
|
||||
"target": "review.checkAccessibility",
|
||||
"kind": "dialog",
|
||||
"target": "accessibility",
|
||||
"excel": "Check Accessibility",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -2302,8 +2196,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "RC",
|
||||
"kind": "command",
|
||||
"target": "review.newComment",
|
||||
"kind": "dialog",
|
||||
"target": "comment",
|
||||
"excel": "New Comment",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -2346,8 +2240,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "RPS",
|
||||
"kind": "command",
|
||||
"target": "review.protectSheet",
|
||||
"kind": "dialog",
|
||||
"target": "protectSheet",
|
||||
"excel": "Protect Sheet",
|
||||
"note": ""
|
||||
},
|
||||
|
|
@ -2368,8 +2262,8 @@
|
|||
},
|
||||
{
|
||||
"seq": "RS",
|
||||
"kind": "command",
|
||||
"target": "review.spelling",
|
||||
"kind": "dialog",
|
||||
"target": "spelling",
|
||||
"excel": "Spelling",
|
||||
"note": ""
|
||||
},
|
||||
|
|
|
|||
|
|
@ -358,6 +358,101 @@ fn popup_command(forced: bool, clicked: bool) -> Option<egui::SetOpenCommand> {
|
|||
if forced { Some(egui::SetOpenCommand::Bool(true)) } else { clicked.then_some(egui::SetOpenCommand::Toggle) }
|
||||
}
|
||||
|
||||
/// Per-control state of an [`editable_combo`]: the filter text and highlighted row.
|
||||
#[derive(Clone, Default)]
|
||||
struct ComboState {
|
||||
text: String,
|
||||
sel: i32,
|
||||
was_open: bool,
|
||||
}
|
||||
|
||||
/// What the user did with an [`editable_combo`].
|
||||
enum ComboResult {
|
||||
None,
|
||||
/// A row was applied: clicked or Enter on the highlighted row.
|
||||
Picked(String),
|
||||
/// Enter with free text that matches no row (e.g. a custom font size).
|
||||
Entered(String),
|
||||
}
|
||||
|
||||
/// Excel-style dropdown: a filter field (type to narrow the list) plus arrow/Enter selection.
|
||||
/// `items` are `(value, display)`; the value is what comes back. When `forced` (keytip invoke)
|
||||
/// or clicked, the popup opens, focuses the filter field, and selects its text.
|
||||
fn editable_combo(
|
||||
ui: &mut Ui,
|
||||
anchor: &egui::Response,
|
||||
salt: &'static str,
|
||||
current_value: &str,
|
||||
items: &[(&str, String)],
|
||||
forced: bool,
|
||||
) -> ComboResult {
|
||||
let popup_id = anchor.id.with("popup");
|
||||
let state_id = anchor.id.with(salt).with("__combo_state");
|
||||
let mut st = ui.data_mut(|d| d.get_temp::<ComboState>(state_id)).unwrap_or_default();
|
||||
let open_now = egui::Popup::is_id_open(ui.ctx(), popup_id);
|
||||
if open_now && !st.was_open {
|
||||
st.text = String::new();
|
||||
st.sel = items.iter().position(|(v, _)| *v == current_value).map(|i| i as i32).unwrap_or(0);
|
||||
}
|
||||
st.was_open = open_now;
|
||||
let mut result = ComboResult::None;
|
||||
egui::Popup::menu(anchor).open_memory(popup_command(forced, anchor.clicked())).show(|ui| {
|
||||
let text_id = anchor.id.with(salt).with("__combo_text");
|
||||
let te = ui.add(egui::TextEdit::singleline(&mut st.text).id(text_id).desired_width(220.0).hint_text("Type to filter…"));
|
||||
if open_now && !te.has_focus() {
|
||||
ui.ctx().memory_mut(|m| m.request_focus(text_id));
|
||||
// Select all once focus lands so typing replaces the filter.
|
||||
if let Some(mut s) = egui::text_edit::TextEditState::load(ui.ctx(), text_id) {
|
||||
let len = st.text.chars().count();
|
||||
s.cursor.set_char_range(Some(egui::text::CCursorRange::two(egui::text::CCursor::new(0), egui::text::CCursor::new(len))));
|
||||
s.store(ui.ctx(), text_id);
|
||||
}
|
||||
}
|
||||
let lower = st.text.to_lowercase();
|
||||
let filtered: Vec<usize> = items.iter().enumerate().filter(|(_, (_, d))| d.to_lowercase().contains(&lower)).map(|(i, _)| i).collect();
|
||||
ui.input(|i| {
|
||||
if !filtered.is_empty() {
|
||||
let n = filtered.len() as i32;
|
||||
if i.key_pressed(egui::Key::ArrowDown) {
|
||||
st.sel = (st.sel + 1).rem_euclid(n);
|
||||
}
|
||||
if i.key_pressed(egui::Key::ArrowUp) {
|
||||
st.sel = (st.sel - 1).rem_euclid(n);
|
||||
}
|
||||
}
|
||||
if i.key_pressed(egui::Key::Enter) {
|
||||
if filtered.is_empty() {
|
||||
let t = st.text.trim().to_string();
|
||||
if !t.is_empty() {
|
||||
result = ComboResult::Entered(t);
|
||||
}
|
||||
} else {
|
||||
let idx = filtered[st.sel.clamp(0, filtered.len() as i32 - 1) as usize];
|
||||
result = ComboResult::Picked(items[idx].0.to_string());
|
||||
}
|
||||
}
|
||||
});
|
||||
ui.separator();
|
||||
egui::ScrollArea::vertical().max_height(240.0).show(ui, |ui| {
|
||||
for i in &filtered {
|
||||
let (value, disp) = &items[*i];
|
||||
let row = ui.add(egui::Button::selectable(*i as i32 == st.sel, egui::RichText::new(disp)).min_size(vec2(220.0, 20.0)));
|
||||
if row.clicked() {
|
||||
result = ComboResult::Picked(value.to_string());
|
||||
}
|
||||
if row.hovered() {
|
||||
st.sel = *i as i32;
|
||||
}
|
||||
}
|
||||
});
|
||||
if !matches!(result, ComboResult::None) {
|
||||
ui.close();
|
||||
}
|
||||
});
|
||||
ui.data_mut(|d| d.insert_temp(state_id, st));
|
||||
result
|
||||
}
|
||||
|
||||
fn menu_items(app: &mut SheetApp, ui: &mut Ui, items: &[(&str, &str, serde_json::Value)]) {
|
||||
for (label, id, p) in items {
|
||||
if *label == "-" {
|
||||
|
|
@ -594,10 +689,9 @@ fn home(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
}
|
||||
let o = small_button(ui, Icon::Orientation, "", "Orientation", true);
|
||||
for sequence in keytip_table::group_extension(app.keytips.prefix().unwrap_or_default(), &["home.orientation", "dialog:formatCells"]) {
|
||||
keytip(app, ui, sequence, o.rect.center_bottom());
|
||||
}
|
||||
egui::Popup::menu(&o).show(|ui| {
|
||||
control_keytip(app, ui, &o, "home.orientation");
|
||||
let forced_o = invoke(app, "home.orientation");
|
||||
egui::Popup::menu(&o).open_memory(popup_command(forced_o, o.clicked())).show(|ui| {
|
||||
menu_items(
|
||||
app,
|
||||
ui,
|
||||
|
|
@ -944,19 +1038,13 @@ fn home(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
|
||||
fn font_combo(app: &mut SheetApp, ui: &mut Ui, st: &Style) {
|
||||
let mut name = st.font.name.clone();
|
||||
let before = name.clone();
|
||||
let name = st.font.name.clone();
|
||||
let resp = ui.add_sized([150.0, 24.0], egui::Button::new(egui::RichText::new(&name).font(theme::ui_font(12.5))));
|
||||
control_keytip(app, ui, &resp, "home.fontName");
|
||||
let forced = invoke(app, "home.fontName");
|
||||
egui::Popup::menu(&resp).open_memory(popup_command(forced, resp.clicked())).show(|ui| {
|
||||
for f in FONTS {
|
||||
let fam = theme::cell_family(f, false, false);
|
||||
ui.selectable_value(&mut name, f.to_string(), egui::RichText::new(*f).font(egui::FontId::new(14.0, fam)));
|
||||
}
|
||||
});
|
||||
if name != before {
|
||||
act(app, "home.fontName", json!({"name": name}));
|
||||
let items: Vec<(&str, String)> = FONTS.iter().map(|f| (*f, f.to_string())).collect();
|
||||
if let ComboResult::Picked(value) = editable_combo(ui, &resp, "font", &name, &items, forced) {
|
||||
act(app, "home.fontName", json!({"name": value}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -981,19 +1069,24 @@ pub const FONTS: &[&str] = &[
|
|||
];
|
||||
|
||||
fn size_combo(app: &mut SheetApp, ui: &mut Ui, st: &Style) {
|
||||
let mut size = st.font.size;
|
||||
let before = size;
|
||||
let size = st.font.size;
|
||||
let label = if size.fract() == 0.0 { format!("{}", size as i32) } else { format!("{size}") };
|
||||
let resp = ui.add_sized([52.0, 24.0], egui::Button::new(egui::RichText::new(label).font(theme::ui_font(12.5))));
|
||||
let resp = ui.add_sized([52.0, 24.0], egui::Button::new(egui::RichText::new(&label).font(theme::ui_font(12.5))));
|
||||
control_keytip(app, ui, &resp, "home.fontSize");
|
||||
let forced = invoke(app, "home.fontSize");
|
||||
egui::Popup::menu(&resp).open_memory(popup_command(forced, resp.clicked())).show(|ui| {
|
||||
for s in [8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 26.0, 28.0, 36.0, 48.0, 72.0] {
|
||||
ui.selectable_value(&mut size, s, format!("{}", s as i32));
|
||||
let sizes = [8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 26.0, 28.0, 36.0, 48.0, 72.0];
|
||||
let labels: Vec<String> = sizes.iter().map(|s| format!("{}", *s as i32)).collect();
|
||||
let items: Vec<(&str, String)> = labels.iter().map(|s| (s.as_str(), s.clone())).collect();
|
||||
let current = if size.fract() == 0.0 { format!("{}", size as i32) } else { format!("{size}") };
|
||||
let mut apply = |s: &str| {
|
||||
if let Ok(v) = s.parse::<f32>() {
|
||||
act(app, "home.fontSize", json!({"size": v}));
|
||||
}
|
||||
});
|
||||
if size != before {
|
||||
act(app, "home.fontSize", json!({"size": size}));
|
||||
};
|
||||
match editable_combo(ui, &resp, "size", ¤t, &items, forced) {
|
||||
ComboResult::Picked(value) => apply(&value),
|
||||
ComboResult::Entered(text) => apply(&text),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1003,29 +1096,24 @@ fn number_combo(app: &mut SheetApp, ui: &mut Ui, st: &Style) {
|
|||
let current = format!("{kind:?}");
|
||||
let lang = app.ui.language;
|
||||
let sample = app.session.active().and_then(|d| d.wb.active().map(|sh| sh.value(d.selection.active))).unwrap_or_default();
|
||||
let mut picked: Option<&str> = None;
|
||||
let resp = ui.add_sized([150.0, 24.0], egui::Button::new(egui::RichText::new(lang.tr(¤t)).font(theme::ui_font(12.5))));
|
||||
control_keytip(app, ui, &resp, "home.numberFormat");
|
||||
let forced = invoke(app, "home.numberFormat");
|
||||
egui::Popup::menu(&resp).open_memory(popup_command(forced, resp.clicked())).show(|ui| {
|
||||
for name in ["General", "Number", "Currency", "Accounting", "Short Date", "Long Date", "Time", "Percentage", "Fraction", "Scientific", "Text"]
|
||||
{
|
||||
let code = gridcraft_engine::cmd::format::format_code_for(name);
|
||||
let names = ["General", "Number", "Currency", "Accounting", "Short Date", "Long Date", "Time", "Percentage", "Fraction", "Scientific", "Text"];
|
||||
let items: Vec<(&str, String)> = names
|
||||
.iter()
|
||||
.map(|n| {
|
||||
let code = gridcraft_engine::cmd::format::format_code_for(n);
|
||||
let preview = app.session.active().map(|d| gridcraft_engine::display::format(&sample, code, &d.wb).text).unwrap_or_default();
|
||||
let r = ui.add(egui::Button::selectable(current == name, format!("{:<12} {preview}", lang.tr(name))).min_size(vec2(240.0, 22.0)));
|
||||
if r.clicked() {
|
||||
picked = Some(name);
|
||||
}
|
||||
(*n, format!("{:<12} {preview}", lang.tr(n)))
|
||||
})
|
||||
.chain(std::iter::once(("__more", format!("{:>12}", lang.tr("More Number Formats…")))))
|
||||
.collect();
|
||||
if let ComboResult::Picked(value) = editable_combo(ui, &resp, "number", ¤t, &items, forced) {
|
||||
match value.as_str() {
|
||||
"__more" => app.open_dialog("formatCells", json!({"tab": "Number"})),
|
||||
n => act(app, "home.numberFormat", json!({"format": n})),
|
||||
}
|
||||
ui.separator();
|
||||
if ui.button(lang.tr("More Number Formats…")).clicked() {
|
||||
picked = Some("__more");
|
||||
}
|
||||
});
|
||||
match picked {
|
||||
Some("__more") => app.open_dialog("formatCells", json!({"tab": "Number"})),
|
||||
Some(n) => act(app, "home.numberFormat", json!({"format": n})),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1326,11 +1414,11 @@ fn insert(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
for (icon, tip, kind, subs) in [
|
||||
for (icon, tip, cid, subs) in [
|
||||
(
|
||||
Icon::ChartBar,
|
||||
"Column or Bar",
|
||||
"column",
|
||||
"insert.chart.column",
|
||||
vec![
|
||||
("Clustered Column", "column", ""),
|
||||
("Stacked Column", "column", "stacked"),
|
||||
|
|
@ -1342,7 +1430,7 @@ fn insert(app: &mut SheetApp, ui: &mut Ui) {
|
|||
(
|
||||
Icon::ChartLine,
|
||||
"Line or Area",
|
||||
"line",
|
||||
"insert.chart.line",
|
||||
vec![
|
||||
("Line", "line", ""),
|
||||
("Line with Markers", "line", "markers"),
|
||||
|
|
@ -1351,11 +1439,12 @@ fn insert(app: &mut SheetApp, ui: &mut Ui) {
|
|||
("Stacked Area", "area", "stacked"),
|
||||
],
|
||||
),
|
||||
(Icon::ChartPie, "Pie or Doughnut", "pie", vec![("Pie", "pie", ""), ("Doughnut", "doughnut", "")]),
|
||||
(Icon::ChartPie, "Pie or Doughnut", "insert.chart.pie", vec![("Pie", "pie", ""), ("Doughnut", "doughnut", "")]),
|
||||
] {
|
||||
let r = small_button(ui, icon, "", tip, true);
|
||||
let _ = kind;
|
||||
egui::Popup::menu(&r).show(|ui| {
|
||||
control_keytip(app, ui, &r, cid);
|
||||
let forced_c = invoke(app, cid);
|
||||
egui::Popup::menu(&r).open_memory(popup_command(forced_c, r.clicked())).show(|ui| {
|
||||
for (label, k, s) in &subs {
|
||||
if ui.button(*label).clicked() {
|
||||
act(app, "insert.chart", json!({"type": k, "subtype": s}));
|
||||
|
|
@ -1365,16 +1454,18 @@ fn insert(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
for (icon, tip, subs) in [
|
||||
for (icon, tip, cid, subs) in [
|
||||
(
|
||||
Icon::ChartScatter,
|
||||
"Scatter or Bubble",
|
||||
"insert.chart.scatter",
|
||||
vec![("Scatter", "scatter", ""), ("Scatter with Lines", "scatter", "lines"), ("Bubble", "bubble", "")],
|
||||
),
|
||||
(Icon::Chart, "Statistic", vec![("Histogram", "histogram", ""), ("Box & Whisker", "boxWhisker", "")]),
|
||||
(Icon::Chart, "Statistic", "insert.chart.statistic", vec![("Histogram", "histogram", ""), ("Box & Whisker", "boxWhisker", "")]),
|
||||
(
|
||||
Icon::Theme,
|
||||
"Hierarchy & more",
|
||||
"insert.chart.hierarchy",
|
||||
vec![
|
||||
("Treemap", "treemap", ""),
|
||||
("Sunburst", "sunburst", ""),
|
||||
|
|
@ -1387,7 +1478,9 @@ fn insert(app: &mut SheetApp, ui: &mut Ui) {
|
|||
),
|
||||
] {
|
||||
let r = small_button(ui, icon, "", tip, true);
|
||||
egui::Popup::menu(&r).show(|ui| {
|
||||
control_keytip(app, ui, &r, cid);
|
||||
let forced_c = invoke(app, cid);
|
||||
egui::Popup::menu(&r).open_memory(popup_command(forced_c, r.clicked())).show(|ui| {
|
||||
for (label, k, s) in &subs {
|
||||
if ui.button(*label).clicked() {
|
||||
act(app, "insert.chart", json!({"type": k, "subtype": s}));
|
||||
|
|
@ -1403,7 +1496,7 @@ fn insert(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
sep(ui);
|
||||
let sp = big_button(ui, Icon::Sparkline, "Sparklines", "Sparklines", true);
|
||||
anchor_keytip(app, ui, &sp, &["insert.sparkline"]);
|
||||
anchor_keytip(app, ui, &sp, &["dialog:sparkline"]);
|
||||
egui::Popup::menu(&sp).show(|ui| {
|
||||
for (label, kind) in [("Line", "line"), ("Column", "column"), ("Win/Loss", "winLoss")] {
|
||||
if ui.button(label).clicked() {
|
||||
|
|
@ -1418,12 +1511,12 @@ fn insert(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
sep(ui);
|
||||
let __k = big_button(ui, Icon::Link, "Link", "Insert Link (⌘K)", false);
|
||||
control_keytip(app, ui, &__k, "insertLink");
|
||||
control_keytip(app, ui, &__k, "dialog:insertLink");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("insertLink", json!({}));
|
||||
}
|
||||
let __k = big_button(ui, Icon::Comment, "Comment", "New Comment", false);
|
||||
control_keytip(app, ui, &__k, "comment");
|
||||
control_keytip(app, ui, &__k, "dialog:comment");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("comment", json!({"threaded": true}));
|
||||
}
|
||||
|
|
@ -1434,7 +1527,7 @@ fn insert(app: &mut SheetApp, ui: &mut Ui) {
|
|||
act(app, "insert.textBox", json!({}));
|
||||
}
|
||||
let __k = big_button(ui, Icon::PageLayout, "Header &\nFooter", "Header & Footer", false);
|
||||
control_keytip(app, ui, &__k, "headerFooter");
|
||||
control_keytip(app, ui, &__k, "dialog:headerFooter");
|
||||
if __k.clicked() {
|
||||
// As in Excel: Page Layout view, editing the header in place (the dialog is under Page Setup).
|
||||
crate::paper_view::start_editing(app);
|
||||
|
|
@ -1618,7 +1711,7 @@ fn page_layout(app: &mut SheetApp, ui: &mut Ui) {
|
|||
|
||||
fn formulas(app: &mut SheetApp, ui: &mut Ui) {
|
||||
let __k = big_button(ui, Icon::Function, "Insert\nFunction", "Insert Function (⇧F3)", false);
|
||||
control_keytip(app, ui, &__k, "insertFunction");
|
||||
control_keytip(app, ui, &__k, "dialog:insertFunction");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("insertFunction", json!({}));
|
||||
}
|
||||
|
|
@ -1627,17 +1720,19 @@ fn formulas(app: &mut SheetApp, ui: &mut Ui) {
|
|||
if s.clicked() {
|
||||
act(app, "formulas.autoSum", json!({}));
|
||||
}
|
||||
for (label, cat) in [
|
||||
("Financial", "Financial"),
|
||||
("Logical", "Logical"),
|
||||
("Text", "Text"),
|
||||
("Date &\nTime", "DateTime"),
|
||||
("Lookup &\nReference", "Lookup"),
|
||||
("Math &\nTrig", "MathTrig"),
|
||||
("More\nFunctions", "Statistical"),
|
||||
for (label, cat, cid) in [
|
||||
("Financial", "Financial", "formulas.financial"),
|
||||
("Logical", "Logical", "formulas.logical"),
|
||||
("Text", "Text", "formulas.text"),
|
||||
("Date &\nTime", "DateTime", "formulas.dateTime"),
|
||||
("Lookup &\nReference", "Lookup", "formulas.lookup"),
|
||||
("Math &\nTrig", "MathTrig", "formulas.mathTrig"),
|
||||
("More\nFunctions", "Statistical", "formulas.moreFunctions"),
|
||||
] {
|
||||
let r = big_button(ui, Icon::Book, label, label, true);
|
||||
egui::Popup::menu(&r).show(|ui| {
|
||||
control_keytip(app, ui, &r, cid);
|
||||
let forced_c = invoke(app, cid);
|
||||
egui::Popup::menu(&r).open_memory(popup_command(forced_c, r.clicked())).show(|ui| {
|
||||
ui.set_max_height(420.0);
|
||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||
for f in gridcraft_engine::cmd::formulas::function_list() {
|
||||
|
|
@ -1659,18 +1754,18 @@ fn formulas(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
sep(ui);
|
||||
let __k = big_button(ui, Icon::Name, "Name\nManager", "Name Manager", false);
|
||||
control_keytip(app, ui, &__k, "nameManager");
|
||||
control_keytip(app, ui, &__k, "dialog:nameManager");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("nameManager", json!({}));
|
||||
}
|
||||
ui.vertical(|ui| {
|
||||
let __k = small_button(ui, Icon::Name, "Define Name", "Define Name", false);
|
||||
control_keytip(app, ui, &__k, "defineName");
|
||||
control_keytip(app, ui, &__k, "dialog:defineName");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("defineName", json!({}));
|
||||
}
|
||||
let use_in = small_button(ui, Icon::Function, "Use in Formula", "Use in Formula", true);
|
||||
anchor_keytip(app, ui, &use_in, &["formulas.useInFormula"]);
|
||||
anchor_keytip(app, ui, &use_in, &["formulas.pasteName"]);
|
||||
egui::Popup::menu(&use_in).show(|ui| {
|
||||
let names: Vec<String> = app.session.active().map(|d| d.wb.names.iter().map(|n| n.name.clone()).collect()).unwrap_or_default();
|
||||
for n in names {
|
||||
|
|
@ -1709,12 +1804,12 @@ fn formulas(app: &mut SheetApp, ui: &mut Ui) {
|
|||
act(app, "formulas.showFormulas", json!({}));
|
||||
}
|
||||
let __k = small_button(ui, Icon::Validation, "Error Checking", "Error Checking", false);
|
||||
control_keytip(app, ui, &__k, "errorChecking");
|
||||
control_keytip(app, ui, &__k, "dialog:errorChecking");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("errorChecking", json!({}));
|
||||
}
|
||||
let __k = small_button(ui, Icon::Calc, "Evaluate Formula", "Evaluate Formula", false);
|
||||
control_keytip(app, ui, &__k, "evaluateFormula");
|
||||
control_keytip(app, ui, &__k, "dialog:evaluateFormula");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("evaluateFormula", json!({}));
|
||||
}
|
||||
|
|
@ -1772,7 +1867,7 @@ fn data(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
});
|
||||
let __k = big_button(ui, Icon::SortFilter, "Sort", "Custom Sort", false);
|
||||
control_keytip(app, ui, &__k, "sort");
|
||||
control_keytip(app, ui, &__k, "dialog:sort");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("sort", json!({}));
|
||||
}
|
||||
|
|
@ -1795,7 +1890,7 @@ fn data(app: &mut SheetApp, ui: &mut Ui) {
|
|||
});
|
||||
sep(ui);
|
||||
let __k = big_button(ui, Icon::TextColumns, "Text to\nColumns", "Text to Columns", false);
|
||||
control_keytip(app, ui, &__k, "textToColumns");
|
||||
control_keytip(app, ui, &__k, "dialog:textToColumns");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("textToColumns", json!({}));
|
||||
}
|
||||
|
|
@ -1805,14 +1900,12 @@ fn data(app: &mut SheetApp, ui: &mut Ui) {
|
|||
act(app, "edit.flashFill", json!({}));
|
||||
}
|
||||
let __k = big_button(ui, Icon::Duplicates, "Remove\nDuplicates", "Remove Duplicates", false);
|
||||
control_keytip(app, ui, &__k, "removeDuplicates");
|
||||
control_keytip(app, ui, &__k, "dialog:removeDuplicates");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("removeDuplicates", json!({}));
|
||||
}
|
||||
let dv = big_button(ui, Icon::Validation, "Data\nValidation", "Data Validation", true);
|
||||
for sequence in
|
||||
keytip_table::group_extension(app.keytips.prefix().unwrap_or_default(), &["dialog:dataValidation", "data.circleInvalid", "data.validation"])
|
||||
{
|
||||
for sequence in keytip_table::group_extension(app.keytips.prefix().unwrap_or_default(), &["data.validation", "data.circleInvalid"]) {
|
||||
keytip(app, ui, sequence, dv.rect.center_bottom());
|
||||
}
|
||||
egui::Popup::menu(&dv).show(|ui| {
|
||||
|
|
@ -1860,7 +1953,7 @@ fn data(app: &mut SheetApp, ui: &mut Ui) {
|
|||
act(app, "data.ungroup", json!({}));
|
||||
}
|
||||
let __k = small_button(ui, Icon::Subtotal, "Subtotal", "Subtotal", false);
|
||||
control_keytip(app, ui, &__k, "subtotal");
|
||||
control_keytip(app, ui, &__k, "dialog:subtotal");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("subtotal", json!({}));
|
||||
}
|
||||
|
|
@ -1885,7 +1978,7 @@ fn data(app: &mut SheetApp, ui: &mut Ui) {
|
|||
|
||||
fn review(app: &mut SheetApp, ui: &mut Ui) {
|
||||
let __k = big_button(ui, Icon::Spell, "Spelling", "Spelling (F7)", false);
|
||||
control_keytip(app, ui, &__k, "spelling");
|
||||
control_keytip(app, ui, &__k, "dialog:spelling");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("spelling", json!({}));
|
||||
}
|
||||
|
|
@ -1895,13 +1988,13 @@ fn review(app: &mut SheetApp, ui: &mut Ui) {
|
|||
app.open_dialog("statistics", json!({}));
|
||||
}
|
||||
let __k = big_button(ui, Icon::Validation, "Check\nAccessibility", "Check Accessibility", false);
|
||||
control_keytip(app, ui, &__k, "accessibility");
|
||||
control_keytip(app, ui, &__k, "dialog:accessibility");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("accessibility", json!({}));
|
||||
}
|
||||
sep(ui);
|
||||
let __k = big_button(ui, Icon::Comment, "New\nComment", "New Comment", false);
|
||||
control_keytip(app, ui, &__k, "comment");
|
||||
control_keytip(app, ui, &__k, "dialog:comment");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("comment", json!({"threaded": true}));
|
||||
}
|
||||
|
|
@ -1935,7 +2028,7 @@ fn review(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
}
|
||||
let notes = big_button(ui, Icon::Note, "Notes", "Notes", true);
|
||||
anchor_keytip(app, ui, ¬es, &["review.newNote"]);
|
||||
anchor_keytip(app, ui, ¬es, &["review.nextComment"]);
|
||||
egui::Popup::menu(¬es).show(|ui| {
|
||||
menu_items(
|
||||
app,
|
||||
|
|
@ -1952,7 +2045,7 @@ fn review(app: &mut SheetApp, ui: &mut Ui) {
|
|||
sep(ui);
|
||||
let protected = app.session.active().and_then(|d| d.wb.active().map(|s| s.is_protected())).unwrap_or(false);
|
||||
let __k = big_button(ui, Icon::Lock, if protected { "Unprotect\nSheet" } else { "Protect\nSheet" }, "Protect Sheet", false);
|
||||
control_keytip(app, ui, &__k, "review.protectSheet");
|
||||
control_keytip(app, ui, &__k, "dialog:protectSheet");
|
||||
if __k.clicked() {
|
||||
if protected {
|
||||
app.open_dialog("unprotectSheet", json!({}));
|
||||
|
|
@ -2018,7 +2111,7 @@ fn view(app: &mut SheetApp, ui: &mut Ui) {
|
|||
});
|
||||
sep(ui);
|
||||
let __k = big_button(ui, Icon::Zoom, "Zoom", "Zoom…", false);
|
||||
control_keytip(app, ui, &__k, "zoom");
|
||||
control_keytip(app, ui, &__k, "dialog:zoom");
|
||||
if __k.clicked() {
|
||||
app.open_dialog("zoom", json!({}));
|
||||
}
|
||||
|
|
@ -2035,10 +2128,9 @@ fn view(app: &mut SheetApp, ui: &mut Ui) {
|
|||
}
|
||||
sep(ui);
|
||||
let fp = big_button(ui, Icon::Freeze, "Freeze\nPanes", "Freeze Panes", true);
|
||||
for sequence in keytip_table::group_extension(
|
||||
app.keytips.prefix().unwrap_or_default(),
|
||||
&["view.freezePanes", "view.freezeTopRow", "view.freezeFirstColumn", "view.unfreezePanes"],
|
||||
) {
|
||||
for sequence in
|
||||
keytip_table::group_extension(app.keytips.prefix().unwrap_or_default(), &["view.freezePanes", "view.freezeTopRow", "view.freezeFirstColumn"])
|
||||
{
|
||||
keytip(app, ui, sequence, fp.rect.center_bottom());
|
||||
}
|
||||
egui::Popup::menu(&fp).show(|ui| {
|
||||
|
|
|
|||
|
|
@ -456,6 +456,47 @@ fn control_keytips_open_dropdowns_and_run_handlers() {
|
|||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn editable_combos_filter_by_typing_and_move_by_arrows() {
|
||||
// Open the font dropdown (HFF), type to filter, then Enter to apply.
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, &[Key::H, Key::F, Key::F], false);
|
||||
h.run_steps(3); // let the filter field gain focus
|
||||
events(&mut h, [Event::Text("arial".into())]);
|
||||
h.run_steps(3);
|
||||
// "arial" matches Arial only — Georgia must be filtered out of the list.
|
||||
assert_eq!(h.query_all_by_label("Georgia").count(), 0, "typing must narrow the list");
|
||||
assert!(h.query_all_by_label("Arial").count() >= 1, "the match must stay visible");
|
||||
key(&mut h, Key::Enter);
|
||||
h.run_steps(3);
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "applying must not raise an error");
|
||||
// The popup closed and the combo button now shows the applied font.
|
||||
assert_eq!(h.query_all_by_label("Arial").count(), 1, "Enter must apply Arial and close the popup");
|
||||
assert_eq!(h.query_all_by_label("Georgia").count(), 0);
|
||||
|
||||
// Arrows alone move through the full list: Calibri -> Cambria -> Candara -> Consolas.
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, &[Key::H, Key::F, Key::F], false);
|
||||
h.run_steps(3);
|
||||
for _ in 0..3 {
|
||||
key(&mut h, Key::ArrowDown);
|
||||
}
|
||||
key(&mut h, Key::Enter);
|
||||
h.run_steps(3);
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none());
|
||||
assert_eq!(h.query_all_by_label("Consolas").count(), 1, "Down x3 from Calibri must land on Consolas");
|
||||
|
||||
// Size combo: type a custom size not in the list, Enter applies it.
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, &[Key::H, Key::F, Key::S], false);
|
||||
h.run_steps(3);
|
||||
events(&mut h, [Event::Text("13.5".into())]);
|
||||
key(&mut h, Key::Enter);
|
||||
h.run_steps(3);
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "custom sizes must apply");
|
||||
assert_eq!(h.query_all_by_label("13.5").count(), 1, "the button must show the custom size");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_sequence_terminates_without_panicking() {
|
||||
use gridcraft_ui_egui::keytips::keytip_table::SEQUENCES;
|
||||
|
|
|
|||
|
|
@ -487,7 +487,7 @@ fn keytip_hdc_() {
|
|||
fn keytip_hdd_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "HDD", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "home.deleteCells"), "HDD must journal home.deleteCells");
|
||||
assert!(h.state().dialog.is_some(), "HDD must open the deleteCells dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -603,7 +603,7 @@ fn keytip_hfdr_() {
|
|||
fn keytip_hfds_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "HFDS", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "edit.goToSpecial"), "HFDS must journal edit.goToSpecial");
|
||||
assert!(h.state().dialog.is_some(), "HFDS must open the goToSpecial dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -677,7 +677,7 @@ fn keytip_hfir_() {
|
|||
fn keytip_hfis_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "HFIS", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "edit.fillSeries"), "HFIS must journal edit.fillSeries");
|
||||
assert!(h.state().dialog.is_some(), "HFIS must open the series dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -712,27 +712,8 @@ fn keytip_hfp_() {
|
|||
fn keytip_hfq_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "HFQ", false);
|
||||
assert_eq!(h.state().keytips.prefix(), Some("HFQ"), "HFQ must stay armed waiting for more input");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_hfql_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "HFQL", false);
|
||||
assert!(h.state().dialog.is_none(), "HFQL must not open a dialog");
|
||||
assert!(h.state().message.is_none(), "HFQL must not open a message box");
|
||||
assert!(h.state().toast.is_none(), "HFQL must not raise a toast");
|
||||
assert!(h.state().session.journal.is_empty(), "HFQL must not journal");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_hfqo_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "HFQO", false);
|
||||
assert!(h.state().dialog.is_none(), "HFQO must not open a dialog");
|
||||
assert!(h.state().message.is_none(), "HFQO must not open a message box");
|
||||
assert!(h.state().toast.is_none(), "HFQO must not raise a toast");
|
||||
assert!(h.state().session.journal.is_empty(), "HFQO must not journal");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "HFQ must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -762,14 +743,14 @@ fn keytip_hic_() {
|
|||
fn keytip_hie_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "HIE", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "home.insertCells"), "HIE must journal home.insertCells");
|
||||
assert!(h.state().dialog.is_some(), "HIE must open the insertCells dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_hii_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "HII", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "home.insertCells"), "HII must journal home.insertCells");
|
||||
assert!(h.state().dialog.is_some(), "HII must open the insertCells dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -966,7 +947,7 @@ fn keytip_hom_() {
|
|||
fn keytip_hop_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "HOP", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "review.protectSheet"), "HOP must journal review.protectSheet");
|
||||
assert!(h.state().dialog.is_some(), "HOP must open the protectSheet dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1169,7 +1150,8 @@ fn keytip_hx_() {
|
|||
fn keytip_nc1_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "NC1", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "insert.chart"), "NC1 must journal insert.chart");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "NC1 must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1183,7 +1165,7 @@ fn keytip_nc2_() {
|
|||
fn keytip_ncm_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "NCM", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "review.newComment"), "NCM must journal review.newComment");
|
||||
assert!(h.state().dialog.is_some(), "NCM must open the comment dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1197,7 +1179,8 @@ fn keytip_ncb_() {
|
|||
fn keytip_nd_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "ND", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "insert.chart"), "ND must journal insert.chart");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "ND must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1235,7 +1218,7 @@ fn keytip_nfpf_() {
|
|||
fn keytip_nh1_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "NH1", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "pageLayout.headerFooter"), "NH1 must journal pageLayout.headerFooter");
|
||||
assert!(h.state().dialog.is_some(), "NH1 must open the headerFooter dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1249,7 +1232,8 @@ fn keytip_nhf_() {
|
|||
fn keytip_nhi_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "NHI", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "insert.chart"), "NHI must journal insert.chart");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "NHI must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1263,7 +1247,7 @@ fn keytip_ni1_() {
|
|||
fn keytip_ni2_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "NI2", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "insert.link"), "NI2 must journal insert.link");
|
||||
assert!(h.state().dialog.is_some(), "NI2 must open the insertLink dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1294,7 +1278,8 @@ fn keytip_nm2_() {
|
|||
fn keytip_nn1_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "NN1", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "insert.chart"), "NN1 must journal insert.chart");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "NN1 must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1343,7 +1328,8 @@ fn keytip_npo_() {
|
|||
fn keytip_nq_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "NQ", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "insert.chart"), "NQ must journal insert.chart");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "NQ must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1357,7 +1343,8 @@ fn keytip_nr_() {
|
|||
fn keytip_nsa_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "NSA", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "insert.chart"), "NSA must journal insert.chart");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "NSA must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1613,7 +1600,7 @@ fn keytip_prs_() {
|
|||
fn keytip_psp_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "PSP", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "pageLayout.pageSetup"), "PSP must journal pageLayout.pageSetup");
|
||||
assert!(h.state().dialog.is_some(), "PSP must open the pageSetup dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1721,35 +1708,23 @@ fn keytip_md_() {
|
|||
fn keytip_me_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "ME", false);
|
||||
assert_eq!(h.state().keytips.prefix(), Some("ME"), "ME must stay armed waiting for more input");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mef_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MEF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MEF must journal formulas.insertFunction");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "ME must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mf_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MF must journal formulas.insertFunction");
|
||||
assert!(h.state().dialog.is_some(), "MF must open the insertFunction dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mg_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MG", false);
|
||||
assert_eq!(h.state().keytips.prefix(), Some("MG"), "MG must stay armed waiting for more input");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mgf_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MGF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MGF must journal formulas.insertFunction");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "MG must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1770,14 +1745,8 @@ fn keytip_mi_() {
|
|||
fn keytip_mi1_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MI1", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MI1 must journal formulas.insertFunction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mif_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MIF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MIF must journal formulas.insertFunction");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "MI1 must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1798,49 +1767,37 @@ fn keytip_mk_() {
|
|||
fn keytip_mkk_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MKK", false);
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "MKK must run formulas.errorChecking cleanly");
|
||||
assert!(h.state().dialog.is_some(), "MKK must open the errorChecking dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_ml_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "ML", false);
|
||||
assert_eq!(h.state().keytips.prefix(), Some("ML"), "ML must stay armed waiting for more input");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mlf_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MLF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MLF must journal formulas.insertFunction");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "ML must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mm_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MM", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.defineName"), "MM must journal formulas.defineName");
|
||||
assert!(h.state().dialog.is_some(), "MM must open the defineName dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mn_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MN", false);
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "MN must run formulas.nameManager cleanly");
|
||||
assert!(h.state().dialog.is_some(), "MN must open the nameManager dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mo_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MO", false);
|
||||
assert_eq!(h.state().keytips.prefix(), Some("MO"), "MO must stay armed waiting for more input");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mof_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MOF", false);
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "MOF must run formulas.lookupReference cleanly");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "MO must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1854,63 +1811,8 @@ fn keytip_mp_() {
|
|||
fn keytip_mq_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MQ", false);
|
||||
assert_eq!(h.state().keytips.prefix(), Some("MQ"), "MQ must stay armed waiting for more input");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mqcf_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MQCF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MQCF must journal formulas.insertFunction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mqef_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MQEF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MQEF must journal formulas.insertFunction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mqif_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MQIF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MQIF must journal formulas.insertFunction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mqof_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MQOF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MQOF must journal formulas.insertFunction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mqsf_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MQSF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MQSF must journal formulas.insertFunction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mqwf_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MQWF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MQWF must journal formulas.insertFunction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mr_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MR", false);
|
||||
assert_eq!(h.state().keytips.prefix(), Some("MR"), "MR must stay armed waiting for more input");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mrf_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MRF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MRF must journal formulas.insertFunction");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "MQ must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1934,14 +1836,8 @@ fn keytip_msp_() {
|
|||
fn keytip_mt_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MT", false);
|
||||
assert_eq!(h.state().keytips.prefix(), Some("MT"), "MT must stay armed waiting for more input");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keytip_mtf_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "MTF", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "formulas.insertFunction"), "MTF must journal formulas.insertFunction");
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "MT must route to its control without an error box");
|
||||
assert_eq!(h.state().keytips.prefix(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2039,7 +1935,7 @@ fn keytip_mxp_() {
|
|||
fn keytip_ab_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "AB", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "data.subtotal"), "AB must journal data.subtotal");
|
||||
assert!(h.state().dialog.is_some(), "AB must open the subtotal dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2060,7 +1956,7 @@ fn keytip_ad_() {
|
|||
fn keytip_ae_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "AE", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "data.textToColumns"), "AE must journal data.textToColumns");
|
||||
assert!(h.state().dialog.is_some(), "AE must open the textToColumns dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2200,7 +2096,7 @@ fn keytip_ak_() {
|
|||
fn keytip_am_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "AM", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "data.removeDuplicates"), "AM must journal data.removeDuplicates");
|
||||
assert!(h.state().dialog.is_some(), "AM must open the removeDuplicates dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2394,7 +2290,7 @@ fn keytip_asd_() {
|
|||
fn keytip_ass_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "ASS", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "data.sort"), "ASS must journal data.sort");
|
||||
assert!(h.state().dialog.is_some(), "ASS must open the sort dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2508,7 +2404,7 @@ fn keytip_ay_() {
|
|||
fn keytip_ra1_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "RA1", false);
|
||||
assert!(h.state().message.is_none() && h.state().toast.is_none(), "RA1 must run review.checkAccessibility cleanly");
|
||||
assert!(h.state().dialog.is_some(), "RA1 must open the accessibility dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2525,7 +2421,7 @@ fn keytip_ra2_() {
|
|||
fn keytip_rc_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "RC", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "review.newComment"), "RC must journal review.newComment");
|
||||
assert!(h.state().dialog.is_some(), "RC must open the comment dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2576,7 +2472,7 @@ fn keytip_ro_() {
|
|||
fn keytip_rps_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "RPS", false);
|
||||
assert!(h.state().session.journal.iter().any(|(id, _)| id == "review.protectSheet"), "RPS must journal review.protectSheet");
|
||||
assert!(h.state().dialog.is_some(), "RPS must open the protectSheet dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2600,7 +2496,7 @@ fn keytip_rrs_() {
|
|||
fn keytip_rs_() {
|
||||
let mut h = harness(blank());
|
||||
sequence(&mut h, "RS", false);
|
||||
assert!(h.state().message.is_some() || h.state().toast.is_some(), "RS must invoke review.spelling and surface its missing-params error");
|
||||
assert!(h.state().dialog.is_some(), "RS must open the spelling dialog");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -3033,7 +2929,7 @@ fn keytip_9_() {
|
|||
|
||||
#[test]
|
||||
fn generated_test_count_matches_the_table() {
|
||||
const EXPECTED: usize = 397;
|
||||
const EXPECTED: usize = 381;
|
||||
assert_eq!(gridcraft_ui_egui::keytips::keytip_table::SEQUENCES.len(), EXPECTED);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue