# clementwzk/opencalc architecture

> Architecture diagram of the GitHub repository clementwzk/opencalc, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-28). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/clementwzk/opencalc
- Repository: https://github.com/clementwzk/opencalc

## Overview

1. **Product shape**
   - OpenCalc is a single-module Android application packaged in `app/`, with no server-side component or networked backend in the repository.
   - The app is centered on local, offline calculator interaction: user input, expression parsing/evaluation, result formatting, and optional history persistence.

2. **Top-level runtime boundary**
   - The Android app is initialized by `OpenCalcApp.kt`, then driven through a small set of Activities and one Quick Settings tile service.
   - The main runtime surfaces are `MainActivity`, `SettingsActivity`, `AboutActivity`, and `MyTileService`.

3. **Primary UI surface**
   - `MainActivity` is the core calculator screen and likely owns the keypad/display interaction, orientation-aware layouts, and history access.
   - The repository includes multiple layout qualifiers (`land`, `sw600dp`, `sw720dp`, etc.), showing that the UI adapts across phone/tablet and portrait/landscape form factors.
   - The app uses XML layouts and menus rather than a fully Compose-based UI.

4. **Expression engine**
   - The calculator logic is isolated under `calculator/`.
   - `Calculator.kt` is the execution-facing entry point, while `parser/Expression.kt` and `parser/NumberFormatter.kt` indicate a custom algebra/parser layer and formatting layer.
   - This is the main non-UI subsystem: it transforms user-entered expressions into evaluated values and formatted display strings.

5. **Data flow: input to result**
   - User actions from the main screen flow into the calculator engine.
   - Expressions are parsed and evaluated locally, then results are formatted for display using the number formatter.
   - The evaluation result can then be pushed into the history subsystem and reused by the UI.

6. **History subsystem**
   - `history/History.kt` and `history/HistoryAdapter.kt` indicate a local history model plus a RecyclerView-style adapter for rendering prior calculations.
   - History is a first-class UI feature rather than a separate storage service; it likely backs the expandable history panel or drawer visible from the main activity.

7. **Preferences and settings**
   - `MyPreferences.kt`, `Themes.kt`, and `util/MyPreferenceMigrator.kt` show that user configuration is stored locally and migrated between app versions.
   - `SettingsActivity` exposes user-facing configuration such as theme choice, scientific mode, precision, numbering system, vibration, and other calculator behavior.
   - Preferences act as the main cross-cutting state source for UI, formatting, and feature toggles.

8. **Theme and presentation layer**
   - The app has multiple themes: dark, light, AMOLED, and Material You support is called out in the README.
   - `Themes.kt` plus resource files in `values-night`, `styles.xml`, `colors.xml`, and themed drawables drive the visual system.
   - `TextSizeAdjuster.kt` suggests the display adapts font size dynamically to keep long expressions/results readable.

9. **Quick Settings / lock-screen integration**
   - `services/MyTileService.kt` is an Android SystemUI tile entry point, giving the app a shortcut outside the main activity.
   - The README’s “available on locked screen” feature implies the tile or activity flow is designed to work without deep app navigation and possibly from the lock screen context.

10. **Dialogs and auxiliary flows**
    - `dialogs/DonationDialog.kt` and `AboutActivity` provide secondary product flows: support, app info, and external links.
    - These are UI-only boundaries that do not affect the calculator engine but do affect navigation and user retention.

11. **Locale and internationalization**
    - The repository is heavily localized: there are many `values-xx` resource directories and a `locales_config.xml`.
    - This means text, numbering/labels, and possibly formatted strings are designed to be language-aware at the resource layer rather than in code.
    - The app’s architecture therefore separates stable logic from locale-specific presentation.

12. **Resource-driven UI assets**
    - The app relies on vector drawables and XML menus for all calculator icons and action affordances.
    - The resource tree contains dedicated layouts for history items and the main screen, showing that UI composition is primarily declarative and resource-based.

13. **Testing boundaries**
    - Unit tests focus on the pure logic layer: `ExpressionUnitTest.kt` and `NumberFormatterTest.kt`.
    - Instrumented tests cover Android runtime behavior via `MainActivityTests.kt`.
    - This split reflects the architecture: algorithmic correctness is isolated from Android UI/runtime verification.

14. **Build and release pipeline**
    - The project uses Gradle Kotlin DSL with version catalog support and the standard Android Gradle build.
    - `fastlane/metadata/android/` and `playStore/` indicate a release/marketing pipeline for app store metadata, screenshots, and changelogs, separate from app runtime code.
    - This does not affect in-app architecture, but it does show the repo includes distribution assets for multiple stores.

15. **Overall system boundary**
    - The clearest architectural boundary is between the Android presentation layer and the local calculator engine.
    - Everything important happens on-device: UI, expression evaluation, formatting, history, settings, and service integration.
    - No external API, database server, or sync backend appears to be part of the system.

Main entry points: [`app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt`](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt) (Main screen), [`app/src/main/java/com/darkempire78/opencalculator/OpenCalcApp.kt`](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/OpenCalcApp.kt) (OpenCalcApp), [`app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt`](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt) (Preferences), [`app/src/main/res/layout/activity_main.xml`](https://github.com/clementwzk/opencalc/blob/main/app/src/main/res/layout/activity_main.xml) (Layouts)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_group_app["Android app"]
  node_node_app(("OpenCalcApp<br/>[OpenCalcApp.kt]"))
  node_node_main_activity["Main screen<br/>Activity<br/>[MainActivity.kt]"]
  node_node_settings_activity["Settings<br/>Activity"]
  node_node_about_activity["About<br/>Activity<br/>[AboutActivity.kt]"]
  node_node_tile_service["Tile service<br/>SystemUI service<br/>[MyTileService.kt]"]
  node_node_preferences[("Preferences<br/>Local settings<br/>[MyPreferences.kt]")]
  node_node_migrator["Migrator<br/>Prefs migration"]
  node_node_themes["Themes<br/>Presentation rules<br/>[Themes.kt]"]
  node_node_textsize["Text sizing<br/>UI utility"]
  node_node_history[("History<br/>Local model<br/>[History.kt]")]
  node_node_history_adapter["History list<br/>Adapter<br/>[HistoryAdapter.kt]"]
  node_node_donation["Donation dialog<br/>[DonationDialog.kt]"]
  node_node_scientific["Scientific mode<br/>Mode logic<br/>[ScientificMode.kt]"]
end

subgraph group_group_calc["Calculator engine"]
  node_node_calculator{{"Calculator<br/>Engine entry<br/>[Calculator.kt]"}}
  node_node_expression{{"Expression<br/>Parser<br/>[Expression.kt]"}}
  node_node_formatter{{"Number format<br/>Formatter<br/>[NumberFormatter.kt]"}}
end

subgraph group_group_resources["Resources"]
  node_node_layouts["Layouts<br/>XML UI<br/>[activity_main.xml]"]
  node_node_resource_theme["Theme resources<br/>XML style assets<br/>[styles.xml]"]
  node_node_locales["Locales<br/>[locales_config.xml]"]
end

subgraph group_group_release["Release assets"]
  node_node_store["Store assets<br/>Release metadata"]
end

subgraph group_group_tests["Tests"]
  node_node_test_logic["Logic tests<br/>Unit tests"]
  node_node_test_android["Android tests<br/>Instrumented tests"]
end

node_node_app -->|"starts"| node_node_main_activity
node_node_app -->|"opens"| node_node_settings_activity
node_node_app -->|"opens"| node_node_about_activity
node_node_app -->|"registers"| node_node_tile_service
node_node_main_activity -->|"input to eval"| node_node_calculator
node_node_calculator -->|"parses"| node_node_expression
node_node_expression -->|"formats"| node_node_formatter
node_node_main_activity -->|"records"| node_node_history
node_node_history_adapter -->|"renders"| node_node_history
node_node_main_activity -->|"shows"| node_node_history_adapter
node_node_settings_activity -->|"reads/writes"| node_node_preferences
node_node_preferences -->|"migrates"| node_node_migrator
node_node_preferences -->|"drives"| node_node_themes
node_node_preferences -->|"configures"| node_node_scientific
node_node_themes -->|"uses"| node_node_resource_theme
node_node_main_activity -->|"adapts display"| node_node_textsize
node_node_layouts -->|"defines UI"| node_node_main_activity
node_node_layouts -->|"defines UI"| node_node_settings_activity
node_node_layouts -->|"defines UI"| node_node_about_activity
node_node_locales -->|"localizes"| node_node_layouts
node_node_test_logic -->|"verifies"| node_node_expression
node_node_test_logic -->|"verifies"| node_node_formatter
node_node_test_android -->|"verifies"| node_node_main_activity
node_node_store -.->|"packages"| node_node_app

click node_node_app "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/OpenCalcApp.kt"
click node_node_main_activity "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt"
click node_node_settings_activity "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/activities/SettingsActivity.kt"
click node_node_about_activity "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/activities/AboutActivity.kt"
click node_node_tile_service "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/services/MyTileService.kt"
click node_node_preferences "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt"
click node_node_migrator "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/util/MyPreferenceMigrator.kt"
click node_node_themes "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/Themes.kt"
click node_node_textsize "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/TextSizeAdjuster.kt"
click node_node_history "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/history/History.kt"
click node_node_history_adapter "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/history/HistoryAdapter.kt"
click node_node_donation "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/dialogs/DonationDialog.kt"
click node_node_calculator "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/calculator/Calculator.kt"
click node_node_expression "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/calculator/parser/Expression.kt"
click node_node_formatter "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/calculator/parser/NumberFormatter.kt"
click node_node_scientific "https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/util/ScientificMode.kt"
click node_node_layouts "https://github.com/clementwzk/opencalc/blob/main/app/src/main/res/layout/activity_main.xml"
click node_node_resource_theme "https://github.com/clementwzk/opencalc/blob/main/app/src/main/res/values/styles.xml"
click node_node_locales "https://github.com/clementwzk/opencalc/blob/main/app/src/main/res/xml/locales_config.xml"
click node_node_test_logic "https://github.com/clementwzk/opencalc/blob/main/app/src/test/java/com/darkempire78/opencalculator/ExpressionUnitTest.kt"
click node_node_test_android "https://github.com/clementwzk/opencalc/blob/main/app/src/androidTest/java/com/darkempire78/opencalculator/MainActivityTests.kt"
click node_node_store "https://github.com/clementwzk/opencalc/blob/main/fastlane/metadata/android/en-US/full_description.txt"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_node_app,node_node_main_activity,node_node_settings_activity,node_node_about_activity,node_node_tile_service,node_node_preferences,node_node_migrator,node_node_themes,node_node_textsize,node_node_history,node_node_history_adapter,node_node_donation,node_node_scientific toneBlue
class node_node_calculator,node_node_expression,node_node_formatter toneAmber
class node_node_layouts,node_node_resource_theme,node_node_locales toneMint
class node_node_store toneRose
class node_node_test_logic,node_node_test_android toneIndigo
```

## Components

### Android app

Runtime code, UI, and local state on device.

- [OpenCalcApp](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/OpenCalcApp.kt): Application · Initializes the Android app process and shared app state. · `app/src/main/java/com/darkempire78/opencalculator/OpenCalcApp.kt`
- [Main screen](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt): Activity · Primary calculator UI, keypad interaction, and display flow. · `app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt`
- [Settings](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/activities/SettingsActivity.kt): Activity · User preferences and behavior configuration surface. · `app/src/main/java/com/darkempire78/opencalculator/activities/SettingsActivity.kt`
- [About](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/activities/AboutActivity.kt): Activity · App info and secondary navigation flow. · `app/src/main/java/com/darkempire78/opencalculator/activities/AboutActivity.kt`
- [Tile service](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/services/MyTileService.kt): SystemUI service · Quick Settings entry point for launching calculator access. · `app/src/main/java/com/darkempire78/opencalculator/services/MyTileService.kt`
- [Preferences](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt): Local settings · Shared preferences-backed app configuration and migration support. · `app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt`
- [Migrator](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/util/MyPreferenceMigrator.kt): Prefs migration · Upgrades stored settings across app versions. · `app/src/main/java/com/darkempire78/opencalculator/util/MyPreferenceMigrator.kt`
- [Themes](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/Themes.kt): Presentation rules · Theme selection and visual mode wiring. · `app/src/main/java/com/darkempire78/opencalculator/Themes.kt`
- [Text sizing](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/TextSizeAdjuster.kt): UI utility · Adjusts display text for long expressions and results. · `app/src/main/java/com/darkempire78/opencalculator/TextSizeAdjuster.kt`
- [History](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/history/History.kt): Local model · Stores prior calculations for reuse in the UI. · `app/src/main/java/com/darkempire78/opencalculator/history/History.kt`
- [History list](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/history/HistoryAdapter.kt): Adapter · Renders calculation history entries in the main UI. · `app/src/main/java/com/darkempire78/opencalculator/history/HistoryAdapter.kt`
- [Donation dialog](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/dialogs/DonationDialog.kt): Dialog · Secondary support and donation flow. · `app/src/main/java/com/darkempire78/opencalculator/dialogs/DonationDialog.kt`
- [Scientific mode](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/util/ScientificMode.kt): Mode logic · Feature toggles and scientific calculator behavior support. · `app/src/main/java/com/darkempire78/opencalculator/util/ScientificMode.kt`

### Calculator engine

Expression parsing, evaluation, and formatting.

- [Calculator](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/calculator/Calculator.kt): Engine entry · Executes calculator actions and bridges UI input to evaluation. · `app/src/main/java/com/darkempire78/opencalculator/calculator/Calculator.kt`
- [Expression](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/calculator/parser/Expression.kt): Parser · Parses and evaluates calculator expressions. · `app/src/main/java/com/darkempire78/opencalculator/calculator/parser/Expression.kt`
- [Number format](https://github.com/clementwzk/opencalc/blob/main/app/src/main/java/com/darkempire78/opencalculator/calculator/parser/NumberFormatter.kt): Formatter · Formats evaluated values for display and locale behavior. · `app/src/main/java/com/darkempire78/opencalculator/calculator/parser/NumberFormatter.kt`

### Resources

XML layouts, themes, menus, and localized assets.

- [Layouts](https://github.com/clementwzk/opencalc/blob/main/app/src/main/res/layout/activity_main.xml): XML UI · Declarative screens for calculator, settings, about, dialog, and history items. · `app/src/main/res/layout/activity_main.xml`
- [Theme resources](https://github.com/clementwzk/opencalc/blob/main/app/src/main/res/values/styles.xml): XML style assets · Colors, styles, dimens, and night/theme variants. · `app/src/main/res/values/styles.xml`
- [Locales](https://github.com/clementwzk/opencalc/blob/main/app/src/main/res/xml/locales_config.xml): Resource locales · Localized strings and locale configuration for many languages. · `app/src/main/res/xml/locales_config.xml`

### Release assets

Store metadata and marketing materials.

- [Store assets](https://github.com/clementwzk/opencalc/blob/main/fastlane/metadata/android/en-US/full_description.txt): Release metadata · Fastlane and Play Store marketing/release materials. · `fastlane/metadata/android/en-US/full_description.txt`

### Tests

Logic and Android runtime verification.

- [Logic tests](https://github.com/clementwzk/opencalc/blob/main/app/src/test/java/com/darkempire78/opencalculator/ExpressionUnitTest.kt): Unit tests · Pure correctness tests for expression evaluation and formatting. · `app/src/test/java/com/darkempire78/opencalculator/ExpressionUnitTest.kt`
- [Android tests](https://github.com/clementwzk/opencalc/blob/main/app/src/androidTest/java/com/darkempire78/opencalculator/MainActivityTests.kt): Instrumented tests · Runtime verification of calculator behavior on Android. · `app/src/androidTest/java/com/darkempire78/opencalculator/MainActivityTests.kt`

## Connections

- OpenCalcApp → Main screen: starts · App process boots into the main calculator surface.
- OpenCalcApp → Settings: opens · Application exposes settings screen for user configuration.
- OpenCalcApp → About: opens · Application exposes the about/info screen.
- OpenCalcApp → Tile service: registers · App includes a Quick Settings tile entry point.
- Main screen → Calculator: input to eval · User actions are converted into calculator operations.
- Calculator → Expression: parses · Calculator engine delegates expression parsing and evaluation.
- Expression → Number format: formats · Computed values are prepared for display output.
- Main screen → History: records · Completed calculations are added to local history.
- History list → History: renders · History data is bound into a list UI.
- Main screen → History list: shows · Main screen presents prior calculations through the adapter.
- Settings → Preferences: reads/writes · Settings screen persists local user preferences.
- Preferences → Migrator: migrates · Stored settings are upgraded across versions.
- Preferences → Themes: drives · Theme and behavior choices flow from preferences.
- Preferences → Scientific mode: configures · Scientific behavior is controlled by stored preferences.
- Themes → Theme resources: uses · Theme definitions are implemented in resources.
- Main screen → Text sizing: adapts display · Calculator display sizing responds to expression length.
- Layouts → Main screen: defines UI · XML layouts compose the main activity screen.
- Layouts → Settings: defines UI · XML layouts compose the settings screen.
- Layouts → About: defines UI · XML layouts compose the about screen.
- Locales → Layouts: localizes · Strings and locale config supply translated UI text.
- Logic tests → Expression: verifies · Unit tests focus on parser and expression correctness.
- Logic tests → Number format: verifies · Unit tests cover number formatting behavior.
- Android tests → Main screen: verifies · Instrumented tests exercise Android runtime behavior.
- Store assets → OpenCalcApp: packages · Release metadata and marketing assets support distribution.
