Skip to main content

Overview

The UnitConverter class is the main implementation of unit conversion functionality in Windows Calculator. It manages conversion categories, units, conversion ratios, and user input handling. The class supports both standard unit conversions (length, weight, temperature, etc.) and currency conversions through specialized data loaders.

Class Definition

namespace UnitConversionManager {
    class UnitConverter : public IUnitConverter, 
                         public std::enable_shared_from_this<UnitConverter>
}
Header: ~/workspace/source/src/CalcManager/UnitConverter.h

Constructors

UnitConverter(dataLoader)

Constructs a UnitConverter with a single data loader for standard unit conversions.
UnitConverter(_In_ const std::shared_ptr<IConverterDataLoader>& dataLoader);
dataLoader
std::shared_ptr<IConverterDataLoader>
Data loader instance for reading category/unit names and conversion data

UnitConverter(dataLoader, currencyDataLoader)

Constructs a UnitConverter with separate data loaders for standard units and currencies.
UnitConverter(
    _In_ const std::shared_ptr<IConverterDataLoader>& dataLoader,
    _In_ const std::shared_ptr<IConverterDataLoader>& currencyDataLoader
);
dataLoader
std::shared_ptr<IConverterDataLoader>
Data loader for standard unit conversion data
currencyDataLoader
std::shared_ptr<IConverterDataLoader>
Specialized data loader for currency conversion data (can be nullptr)

Core Methods

Initialize

Initializes the converter by loading data from the configured data loaders.
void Initialize();
See UnitConverter.cpp:72

GetCategories

Returns the list of available conversion categories.
std::vector<Category> GetCategories();
Returns: Vector of Category structs representing all available conversion categories (e.g., Length, Weight, Temperature, Currency) See UnitConverter.cpp:89

SetCurrentCategory

Sets the active conversion category and returns initialization data for the category.
CategorySelectionInitializer SetCurrentCategory(const Category& input);
input
const Category&
The category to set as current
Returns: CategorySelectionInitializer (tuple containing: vector of units, from unit, to unit) See UnitConverter.cpp:100

GetCurrentCategory

Retrieves the currently active conversion category.
Category GetCurrentCategory();
Returns: The current Category struct See UnitConverter.cpp:134

SetCurrentUnitTypes

Sets the source and target units for conversion and triggers a calculation.
void SetCurrentUnitTypes(const Unit& fromType, const Unit& toType);
fromType
const Unit&
The unit being converted from (source unit)
toType
const Unit&
The unit being converted to (target unit)
See UnitConverter.cpp:145

Calculate

Performs the conversion calculation based on current input value and selected units.
void Calculate();
This method converts the current display value from the source unit to the target unit, handles precision and formatting, and updates the view model with the result. See UnitConverter.cpp:867

SwitchActive

Swaps the source and target units, switching which field the user is editing.
void SwitchActive(const std::wstring& newValue);
newValue
const std::wstring&
The value from the newly activated field (handles cases where the UI may have trimmed digits)
See UnitConverter.cpp:176

IsSwitchedActive

Checks whether the user has switched to editing the target field.
bool IsSwitchedActive() const;
Returns: true if the user is editing the target field, false otherwise See UnitConverter.cpp:199

SendCommand

Processes input commands from the user interface (number keys, decimal, backspace, etc.).
void SendCommand(Command command);
command
Command
The command enum representing the user action (e.g., Zero, One, Decimal, Backspace, Negate, Clear)
See UnitConverter.cpp:393

RefreshCurrencyRatios

Asynchronously refreshes currency conversion rates from the web.
std::future<std::pair<bool, std::wstring>> RefreshCurrencyRatios();
Returns: Future containing a pair of (success flag, timestamp string) See UnitConverter.cpp:558

Persistence Methods

SaveUserPreferences

Serializes the current converter state to a string for persistence.
std::wstring SaveUserPreferences();
Returns: Serialized string containing the current category, from unit, and to unit See UnitConverter.cpp:314

RestoreUserPreferences

Deserializes and restores the converter state from a saved string.
void RestoreUserPreferences(std::wstring_view userPreferences);
userPreferences
std::wstring_view
Serialized state string from a previous SaveUserPreferences() call
See UnitConverter.cpp:278

Callback Methods

SetViewModelCallback

Registers a callback interface for display updates.
void SetViewModelCallback(
    _In_ const std::shared_ptr<IUnitConverterVMCallback>& newCallback
);
newCallback
std::shared_ptr<IUnitConverterVMCallback>
Callback interface that receives conversion results and suggested values
See UnitConverter.cpp:538

SetViewModelCurrencyCallback

Registers a callback interface for currency-specific updates.
void SetViewModelCurrencyCallback(
    _In_ const std::shared_ptr<IViewModelCurrencyCallback>& newCallback
);
newCallback
std::shared_ptr<IViewModelCurrencyCallback>
Callback interface for currency symbols, ratios, timestamps, and network status
See UnitConverter.cpp:547

Utility Methods

StringToVector

Parses a delimited string into a vector of strings.
static std::vector<std::wstring> StringToVector(
    std::wstring_view w,
    std::wstring_view delimiter,
    bool addRemainder = false
);
w
std::wstring_view
The string to parse
delimiter
std::wstring_view
The delimiter to split on
addRemainder
bool
default:"false"
Whether to include any remaining text after the last delimiter
Returns: Vector of parsed string tokens See UnitConverter.cpp:214

Quote

Escapes special delimiter characters in a string for serialization.
static std::wstring Quote(std::wstring_view s);
s
std::wstring_view
The string to escape
Returns: Escaped string with delimiter characters converted to escape sequences See UnitConverter.cpp:330

Unquote

Unescapes a serialized string, restoring original delimiter characters.
static std::wstring Unquote(std::wstring_view s);
s
std::wstring_view
The escaped string to restore
Returns: Original string with escape sequences converted back to delimiter characters See UnitConverter.cpp:354

ResetCategoriesAndRatios

Reloads all categories and conversion ratios from the data loaders.
void ResetCategoriesAndRatios();
See UnitConverter.cpp:724

Data Structures

Unit Struct

Represents a single unit of measurement within a category.
struct Unit {
    int id;
    std::wstring name;
    std::wstring accessibleName;
    std::wstring abbreviation;
    bool isConversionSource;
    bool isConversionTarget;
    bool isWhimsical;
};
id
int
Unique identifier for the unit
name
std::wstring
Display name of the unit (e.g., “Meters”, “Pounds”)
accessibleName
std::wstring
Accessibility-friendly name for screen readers
abbreviation
std::wstring
Short abbreviation (e.g., “m”, “lb”)
isConversionSource
bool
Whether this unit is set as the source (from) unit
isConversionTarget
bool
Whether this unit is set as the target (to) unit
isWhimsical
bool
Whether this is a whimsical/novelty unit (e.g., “Football fields”)
See UnitConverter.h:16

EMPTY_UNIT

A sentinel value representing an uninitialized or invalid unit.
inline const Unit EMPTY_UNIT = Unit{ -1, L"", L"", true, true, false };
See UnitConverter.h:80

Category Struct

Represents a conversion category (e.g., Length, Weight, Currency).
struct Category {
    int id;
    std::wstring name;
    bool supportsNegative;
};
id
int
Unique identifier for the category
name
std::wstring
Display name of the category (e.g., “Length”, “Currency”)
supportsNegative
bool
Whether negative values are allowed in this category
See UnitConverter.h:82

ConversionData Struct

Defines the conversion formula between two units.
struct ConversionData {
    double ratio;
    double offset;
    bool offsetFirst;
};
ratio
double
Multiplication factor for the conversion
offset
double
Additive offset for the conversion (used for temperature, etc.)
offsetFirst
bool
If true, apply offset before ratio: (value + offset) * ratio
If false, apply ratio before offset: (value * ratio) + offset
See UnitConverter.h:126

Constants

  • MAXIMUMDIGITSALLOWED = 15 - Maximum significant digits allowed in input
  • OPTIMALDIGITSALLOWED = 7 - Optimal number of significant digits for display
  • OPTIMALDECIMALALLOWED = 1e-6 - Threshold for optimal decimal precision
  • MINIMUMDECIMALALLOWED = 1e-14 - Minimum decimal value before switching to scientific notation
See UnitConverter.cpp:21

Type Aliases

using CategorySelectionInitializer = std::tuple<
    std::vector<Unit>,  // Available units
    Unit,               // From unit
    Unit                // To unit
>;

using UnitToUnitToConversionDataMap = std::unordered_map<
    Unit,
    std::unordered_map<Unit, ConversionData, UnitHash>,
    UnitHash
>;

using CategoryToUnitVectorMap = std::unordered_map<int, std::vector<Unit>>;
See UnitConverter.h:159

Usage Example

// Create data loaders
auto dataLoader = std::make_shared<ConverterDataLoader>();
auto currencyLoader = std::make_shared<CurrencyDataLoader>();

// Create converter with both loaders
auto converter = std::make_shared<UnitConverter>(dataLoader, currencyLoader);
converter->Initialize();

// Set up callbacks
auto vmCallback = std::make_shared<MyViewModelCallback>();
converter->SetViewModelCallback(vmCallback);

// Get available categories
auto categories = converter->GetCategories();

// Select a category
auto [units, fromUnit, toUnit] = converter->SetCurrentCategory(categories[0]);

// Set conversion units
converter->SetCurrentUnitTypes(units[0], units[1]);

// Send input commands
converter->SendCommand(Command::Five);
converter->SendCommand(Command::Decimal);
converter->SendCommand(Command::Two);

// Calculate and get results via callback
converter->Calculate();

Build docs developers (and LLMs) love