advanced-calculator/docs/migration-plan.md

7.3 KiB
Raw Blame History

Advanced Calculator Migration Plan

Migration target: .NET 4.7 WPF (src.4.7) → Avalonia on .NET 8 (src) with Desktop, Android, and Browser heads.

Objectives

  • Preserve existing features and UX while adopting MVVM and crossplatform patterns.
  • Encapsulate the expression engine behind a service to isolate API differences.
  • Maintain a single shared UI project for all heads; avoid platformspecific code.

Repo Overview

  • New solution (src):
    • AdvancedCalculator (shared UI, Avalonia 11, net8.0)
    • Heads: AdvancedCalculator.Desktop (net8.0), AdvancedCalculator.Android (net8.0-android), AdvancedCalculator.Browser (net8.0-browser)
    • Uses CommunityToolkit.Mvvm and already references CSMic.StandardLibrary.
  • Old project (src.4.7):
    • WPF MainWindow with variables, function definitions panel, history, and input with Enter submit.
    • Icons via Material Design Icons TTF + IconFont.cs glyph map.
    • Models: HistoryItem, VariableItem, FunctionDefinitonItem.
    • Interpreter: csmic.InputInterpreter in code-behind.

High-Level Approach

  1. Port models and static data to the shared project.
  2. Wrap the interpreter in a service (ICalculatorService) that maintains state and exposes async APIs.
  3. Move UI logic from code-behind to MainViewModel using commands and observable collections.
  4. Recreate the WPF layout in Avalonia XAML (MainView.axaml), preserving behavior and styling.
  5. Migrate icons/assets and wire up font usage across platforms.
  6. Polish interactions (auto-scroll, focus, virtualization) and verify crossplatform.

Mapping WPF → Avalonia

  • Events → Commands:
    • txtInput_KeyDown (Enter) → SubmitCommand with KeyBinding on the input TextBox.
    • btnFx_ClickToggleFunctionsCommand.
  • Collections:
    • List<T>ObservableCollection<T> for History and Variables.
  • Visibility:
    • WPF Visibilitybool properties (IsExpression, IsFunctionsPanelOpen) bound to IsVisible or via a simple BoolToGridLength/BoolToVisibility converter.
  • Icons:
    • Keep IconFont glyphs and ship the TTF in Assets/Fonts, or reduce to the required subset.
  • Scrolling:
    • Use ListBox/ListView and set selected index to last; optionally call ScrollIntoView from code-behind or via behavior.

Phased Plan

Phase 1: Models and Service

  • Add Models in src/AdvancedCalculator:
    • HistoryItem.cs (copy shape from WPF)
    • VariableItem.cs (replace Visibility with bool IsExpression and string? ExpressionComputation)
    • FunctionDefinitionItem.cs (rename to fix spelling; copy DefinedFunctions static enumeration)
  • Add Services:
    • ICalculatorService with methods like:
      • Task<InterpretResult> InterpretAsync(string input)
    • CalculatorService that holds a persistent interpreter instance from CSMic.StandardLibrary and returns:
      • Computed Output
      • Current variables (name, value, type)
      • For equation variables: compute and store ExpressionComputation

Notes:

  • The service isolates any API delta between WPFs csmic.InputInterpreter and the current CSMic.StandardLibrary.

Phase 2: ViewModel

  • Expand MainViewModel:
    • Properties: InputText, IsFunctionsPanelOpen, ObservableCollection<HistoryItem> History, ObservableCollection<VariableItem> Variables.
    • Commands: SubmitCommand, ToggleFunctionsCommand using RelayCommand/AsyncRelayCommand.
    • On submit: call CalculatorService.InterpretAsync(InputText), append to History, rebuild Variables, clear InputText, and request UI scroll to last.

Phase 3: UI Layout

  • Update Views/MainView.axaml to mirror WPF layout:
    • Grid with two columns; left hosts Variables (row 0) + Functions panel (row 1, height toggled), right hosts History (row 0) + input row (row 1).
    • Add GridSplitter between columns.
    • Bind ItemsSource for lists and set DataTemplates for item visuals (icon column + text stacks as in WPF XAML).
    • Input row: toggle Button bound to ToggleFunctionsCommand; TextBox bound to InputText with KeyBinding Enter → SubmitCommand.

Phase 4: Icons and Assets

  • Copy materialdesignicons-webfont.ttf to src/AdvancedCalculator/Assets/Fonts.
  • Update AdvancedCalculator.csproj to include the font as an AvaloniaResource.
  • Reference the font in XAML via FontFamily="avares://AdvancedCalculator/Assets/Fonts#Material Design Icons".
  • Optionally copy a slimmed IconFont.cs (only used glyphs) and bind TextBlock to those glyph strings.

Phase 5: Interaction Polish

  • Auto-scroll History on submit (select last item or call ScrollIntoView in code-behind for MainView).
  • Ensure lists use virtualization (default templates are virtualized; confirm template choice preserves it).
  • Focus management: focus input TextBox after submit.

Phase 6: Cross-Platform Verification

  • Desktop: smoke test.
  • Browser: ensure font loads correctly as an Avalonia resource; verify icons render and inputs submit with Enter.
  • Android: verify IME enter (Done/Go) triggers submit; confirm font packaged and renders.

Phase 7: Cleanup and Docs

  • Remove placeholder greeting and unused templates.
  • Update README.md with build/run instructions per target, plus basic usage.
  • (Optional) Add a few unit tests for CalculatorService if practical without heavy harness.

File-Level Checklist

  • Add:
    • src/AdvancedCalculator/Models/HistoryItem.cs
    • src/AdvancedCalculator/Models/VariableItem.cs
    • src/AdvancedCalculator/Models/FunctionDefinitionItem.cs
    • src/AdvancedCalculator/Services/ICalculatorService.cs
    • src/AdvancedCalculator/Services/CalculatorService.cs
    • src/AdvancedCalculator/Assets/Fonts/materialdesignicons-webfont.ttf
  • Update:
    • src/AdvancedCalculator/AdvancedCalculator.csproj (Avalonia resources for Fonts)
    • src/AdvancedCalculator/ViewModels/MainViewModel.cs (properties + commands)
    • src/AdvancedCalculator/Views/MainView.axaml (+ optional code-behind for scroll/focus)

Risks & Mitigations

  • Interpreter API changes: contained by CalculatorService; adjust adapter logic without touching UI.
  • Font payload size (Browser, Android): if large, switch to a reduced subset or alternate icon source.
  • Visibility semantics: prefer bool bindings to IsVisible to avoid platform enums.
  • WebAssembly resource loading: verify avares:// URIs and that the font is included as a resource.

Acceptance Criteria

  • Entering an expression appends to History and updates Variables.
  • Variables defined as equations show computed ExpressionComputation and a distinct icon.
  • Function definitions panel toggles and displays static help list.
  • Icons render on Desktop and Browser; Android renders acceptable icons.
  • Solution builds and runs across Desktop, Browser, and Android heads.

Timeline Estimate

  • Phase 12 (Models, Service, VM): 0.51 day
  • Phase 3 (UI layout and bindings): 11.5 days
  • Phase 45 (Assets, polish): 0.5 day
  • Phase 6 (Crossplatform checks): 0.51 day
  • Total: ~2.54 days including docs and smoke tests

Next Actions

  1. Create Models and Services scaffolding in AdvancedCalculator and wire MainViewModel.
  2. Port the XAML layout and data templates into MainView.axaml.
  3. Add icon font resources and verify rendering on Desktop.
  4. Smoke test on Browser and Android heads; adjust assets if needed.