diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 908a643e..860c9f92 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -8,7 +8,7 @@ assignees: '' --- **Problem Statement** diff --git a/.github/fabricbot.json b/.github/fabricbot.json new file mode 100644 index 00000000..20db2533 --- /dev/null +++ b/.github/fabricbot.json @@ -0,0 +1,1550 @@ +{ + "version": "1.0", + "tasks": [ + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "90dqm0PD7", + "config": { + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Feature Tracking" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "Enhancement" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "Enhancement" + } + } + ] + }, + { + "name": "isOpen", + "parameters": {} + } + ] + }, + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Feature Tracking", + "columnName": "Pitch" + } + }, + { + "name": "addReactionToIssue", + "parameters": { + "reaction": "+1" + } + } + ], + "taskName": "Feature Request: new pitch created" + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "DEo03OM0n", + "config": { + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "Enhancement" + } + }, + { + "name": "isInProject", + "parameters": { + "projectName": "Feature Tracking", + "columnName": "Pitch" + } + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs pitch review" + } + } + ] + }, + "taskName": "Feature Request: \"needs pitch review\" label added to pitch in \"Feature Tracking\" board", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Feature Tracking", + "columnName": "Pitch (Needs Review)" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "needs more info" + } + }, + { + "name": "addReply", + "parameters": { + "comment": "This pitch looks like it has everything it needs for review. In the meantime, we'll keep this idea open for discussion so the community has the chance to provide feedback. Check out our [New Feedback Process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) for more info on the user-centered process we follow for new feature development." + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "J1uYC69hr", + "config": { + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "Enhancement" + } + }, + { + "name": "isInProject", + "parameters": { + "projectName": "Feature Tracking" + } + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs more info" + } + } + ] + }, + "taskName": "Feature Pitch: \"needs more info\" label added to pitch in \"Feature Tracking\" board", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Feature Tracking", + "columnName": "Pitch" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "needs pitch review" + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "EQ-12A2cG", + "config": { + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "Enhancement" + } + }, + { + "name": "isInProject", + "parameters": { + "projectName": "Feature Tracking" + } + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs spec" + } + } + ] + }, + "taskName": "Feature Request: \"needs spec\" label added to pitch in \"Feature Tracking\" board", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Feature Tracking", + "columnName": "Planning" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "needs pitch review" + } + }, + { + "name": "addReply", + "parameters": { + "comment": "We reviewed the pitch and would love to explore this idea further! The pitch is a great start, but there are still some open questions. I am moving this issue into [planning](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md#step-2-planning) to iron out some of those details and I created [calculator-specs/TBD](https://github.com/microsoft/calculator-specs/tree/TBD) to track progress. A human will follow up with some feedback on your pitch shortly. Keep in mind that not all ideas that make it into the planning phase are guaranteed to make it to release. For more information on next steps, check out our [spec workflow](https://github.com/Microsoft/calculator-specs#workflow)." + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "9xOafGaWd", + "config": { + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "Enhancement" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "pitch declined" + } + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Feature Tracking", + "columnName": "Pitch (Needs Review)" + } + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Feature Tracking", + "columnName": "Pitch" + } + } + ] + }, + { + "name": "isInProject", + "parameters": { + "projectName": "Feature Tracking" + } + } + ] + }, + "taskName": "Feature Request: \"pitch declined\" label added to pitch in \"Feature Tracking\" board", + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "Thanks again for submitting your idea! However, after reviewing this pitch more closely, we do not believe it is a great fit for the product at this time. Thank you for your contribution to Calculator!" + } + }, + { + "name": "removeFromProject", + "parameters": { + "projectName": "Feature Tracking", + "isOrgProject": false + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "needs pitch review" + } + }, + { + "name": "closeIssue", + "parameters": {} + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "oZOHQYqIH", + "config": { + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "Enhancement" + } + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Feature Tracking", + "columnName": "Planning" + } + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs spec review" + } + } + ] + }, + "taskName": "Feature Request: \"needs spec review\" label added to pitch in \"Feature Tracking\" board", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "columnName": "Planning (Needs Review)", + "projectName": "Feature Tracking" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "needs spec" + } + }, + { + "name": "addReply", + "parameters": { + "comment": "This feature is ready for spec review! We will leave Microsoft/calculator-specs# open for a little while to give the community the chance to review and provide feedback. Keep in mind that not all ideas that make it into spec review are guaranteed to make it to release. For more information on next steps, check out our [new feature process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) and [spec workflow](https://github.com/Microsoft/calculator-specs#workflow)." + } + } + ] + } + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "id": "tu0JwvC3X", + "config": { + "taskName": "Issues: Add \"no recent activity\" to non-approved issues that are not feature requests", + "frequency": [ + { + "weekDay": 0, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 1, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 2, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 3, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 4, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 5, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 6, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + } + ], + "searchTerms": [ + { + "name": "isIssue", + "parameters": {} + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "noLabel", + "parameters": { + "label": "approved" + } + }, + { + "name": "noLabel", + "parameters": { + "label": "triage approved" + } + }, + { + "name": "noLabel", + "parameters": { + "label": "Enhancement" + } + }, + { + "name": "noLabel", + "parameters": { + "label": "needs attention" + } + }, + { + "name": "noActivitySince", + "parameters": { + "days": 7 + } + } + ], + "actions": [ + { + "name": "addLabel", + "parameters": { + "label": "no recent activity" + } + }, + { + "name": "addReply", + "parameters": { + "comment": "This issue has been automatically marked as stale because it has not had any activity for **7 days**. It will be closed if no further activity occurs **within 7 days of this comment**. Thank you for your contributions to Windows Calculator!" + } + } + ] + }, + "disabled": true + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "id": "TsBGagZo7", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "no recent activity" + } + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issue_comment" + ], + "taskName": "Issues: Remove \"no recent activity\" when an issue is commented on", + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "no recent activity" + } + } + ] + } + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "id": "0e0TMuQWL", + "config": { + "frequency": [ + { + "weekDay": 0, + "hours": [ + 1, + 4, + 7, + 10, + 13, + 16, + 19, + 22 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 1, + "hours": [ + 1, + 4, + 7, + 10, + 13, + 16, + 19, + 22 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 2, + "hours": [ + 1, + 4, + 7, + 10, + 13, + 16, + 19, + 22 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 3, + "hours": [ + 1, + 4, + 7, + 10, + 13, + 16, + 19, + 22 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 4, + "hours": [ + 1, + 4, + 7, + 10, + 13, + 16, + 19, + 22 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 5, + "hours": [ + 1, + 4, + 7, + 10, + 13, + 16, + 19, + 22 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 6, + "hours": [ + 1, + 4, + 7, + 10, + 13, + 16, + 19, + 22 + ], + "timezoneOffset": -8 + } + ], + "taskName": "Issues: Close stale issues", + "searchTerms": [ + { + "name": "isIssue", + "parameters": {} + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "hasLabel", + "parameters": { + "label": "no recent activity" + } + }, + { + "name": "noLabel", + "parameters": { + "label": "triage needed" + } + }, + { + "name": "noActivitySince", + "parameters": { + "days": 7 + } + }, + { + "name": "noLabel", + "parameters": { + "label": "investigate" + } + } + ], + "actions": [ + { + "name": "closeIssue", + "parameters": {} + } + ] + }, + "disabled": true + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "id": "ybTVd5Fwj", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "Issues: Clean up labels on closed issues", + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "needs pitch review" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "needs more info" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "needs spec" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "no recent activity" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "help wanted" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "needs spec review" + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "needs spec" + } + } + ], + "dangerZone": { + "respondToBotActions": true, + "acceptRespondToBotActions": true + } + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestReviewResponder", + "version": "1.0", + "config": { + "taskName": "PR: Add \"needs author feedback\" label to PRs when changes are requested", + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "submitted" + } + }, + { + "name": "isReviewState", + "parameters": { + "state": "changes_requested" + } + } + ] + }, + "actions": [ + { + "name": "addLabel", + "parameters": { + "label": "needs author feedback" + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request_review" + ] + }, + "id": "nx2_P90Rj1", + "disabled": false + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "PR: Remove \"needs author feedback\" label when author responds to a PR", + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isActivitySender", + "parameters": { + "user": { + "type": "author" + } + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + }, + { + "name": "hasLabel", + "parameters": { + "label": "needs author feedback" + } + } + ] + }, + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "needs author feedback" + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ] + }, + "id": "gZuiBhKkyR", + "disabled": false + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestCommentResponder", + "version": "1.0", + "config": { + "taskName": "PR: Remove \"needs author feedback\" label when author comments on PR", + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isActivitySender", + "parameters": { + "user": { + "type": "author" + } + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "needs author feedback" + } + } + ] + }, + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "needs author feedback" + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "issue_comment" + ] + }, + "id": "Glp85WqHJ5", + "disabled": false + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestReviewResponder", + "version": "1.0", + "config": { + "taskName": "PR: Remove \"needs author feedback\" label when author responds to a PR review comment", + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isActivitySender", + "parameters": { + "user": { + "type": "author" + } + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "needs author feedback" + } + } + ] + }, + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "needs author feedback" + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request_review" + ] + }, + "id": "UUCiOR514E", + "disabled": false + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "PR: Remove \"no recent activity\" label from pull requests", + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + }, + { + "name": "hasLabel", + "parameters": { + "label": "no recent activity" + } + } + ] + }, + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "no recent activity" + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ] + }, + "id": "_YRyPxcA1h", + "disabled": false + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestCommentResponder", + "version": "1.0", + "config": { + "taskName": "PR: Remove \"no recent activity\" label when a PR is commented on", + "conditions": { + "operator": "and", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "no recent activity" + } + } + ] + }, + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "no recent activity" + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "issue_comment" + ] + }, + "id": "rEvX0VIqw9", + "disabled": false + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestReviewResponder", + "version": "1.0", + "config": { + "taskName": "PR: Remove \"no recent activity\" label when a PR is reviewed", + "conditions": { + "operator": "and", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "no recent activity" + } + } + ] + }, + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "no recent activity" + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request_review" + ] + }, + "id": "hOTo334CMP", + "disabled": false + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "config": { + "taskName": "PR: Close stale PRs", + "frequency": [ + { + "weekDay": 0, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 1, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 2, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 3, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 4, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 5, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 6, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + } + ], + "searchTerms": [ + { + "name": "isPr", + "parameters": {} + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "hasLabel", + "parameters": { + "label": "needs author feedback" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "no recent activity" + } + }, + { + "name": "noActivitySince", + "parameters": { + "days": 7 + } + } + ], + "actions": [ + { + "name": "closeIssue", + "parameters": {} + } + ] + }, + "id": "ki5HqIKb5w", + "disabled": true + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "config": { + "taskName": "PR: Add \"no recent activity\" label to PRs", + "frequency": [ + { + "weekDay": 0, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 1, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 2, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 3, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 4, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 5, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + }, + { + "weekDay": 6, + "hours": [ + 2, + 5, + 8, + 11, + 14, + 17, + 20, + 23 + ], + "timezoneOffset": -8 + } + ], + "searchTerms": [ + { + "name": "isPr", + "parameters": {} + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "hasLabel", + "parameters": { + "label": "needs author feedback" + } + }, + { + "name": "noActivitySince", + "parameters": { + "days": 7 + } + }, + { + "name": "noLabel", + "parameters": { + "label": "no recent activity" + } + } + ], + "actions": [ + { + "name": "addLabel", + "parameters": { + "label": "no recent activity" + } + }, + { + "name": "addReply", + "parameters": { + "comment": "This pull request has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **7 days**. Thank you for your contributions to Windows Calculator!" + } + } + ] + }, + "id": "NuVE9uOkcA", + "disabled": false + }, + { + "taskType": "trigger", + "capabilityId": "AutoMerge", + "subCapability": "AutoMerge", + "version": "1.0", + "config": { + "taskName": "PR: Automatically merge PRs", + "label": "AutoMerge", + "silentMode": false, + "minMinutesOpen": 480, + "mergeType": "squash" + }, + "id": "6EONuAShR1", + "disabled": true + }, + { + "taskType": "trigger", + "capabilityId": "EmailCleanser", + "subCapability": "EmailCleanser", + "version": "1.0", + "id": "4XBi1jeNi", + "config": { + "taskName": "Email Reply Cleaner" + } + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "config": { + "frequency": [ + { + "weekDay": 0, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 1, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 2, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 3, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 4, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 5, + "hours": [ + 0, + 6, + 12, + 18 + ] + }, + { + "weekDay": 6, + "hours": [ + 0, + 6, + 12, + 18 + ] + } + ], + "searchTerms": [ + { + "name": "isClosed", + "parameters": {} + }, + { + "name": "noActivitySince", + "parameters": { + "days": 30 + } + }, + { + "name": "isUnlocked", + "parameters": {} + }, + { + "name": "isIssue", + "parameters": {} + } + ], + "taskName": "Lock issues closed without activity for over 30 days", + "actions": [ + { + "name": "lockIssue", + "parameters": { + "reason": "resolved" + } + } + ] + }, + "id": "53dIr53Wxp" + } + ], + "userGroups": [] +} diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b50c909a..556c4067 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,7 +7,7 @@ - ### How changes were validated: - - diff --git a/.gitignore b/.gitignore index 0167a23c..ed4b08c6 100644 --- a/.gitignore +++ b/.gitignore @@ -93,6 +93,9 @@ ipch/ *.vspx *.sap +# Visual Studio Code +.vscode/ + # TFS 2012 Local Workspace $tf/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 63702de4..93e24ce2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,7 +70,7 @@ should be used where automated testing is not feasible. ### Git workflow Calculator uses the [GitHub flow](https://guides.github.com/introduction/flow/) where most -development happens directly on the `master` branch. The `master` branch should always be in a +development happens directly on the `main` branch. The `main` branch should always be in a healthy state which is ready for release. If your change is complex, please clean up the branch history before submitting a pull request. diff --git a/NOTICE.txt b/NOTICE.txt index adfcd323..d115a691 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -37,211 +37,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ---- - -Appium DotNet Driver - -Copyright 2014-2015 Appium Contributors - -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, -and distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by -the copyright owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all -other entities that control, are controlled by, or are under common -control with that entity. For the purposes of this definition, -"control" means (i) the power, direct or indirect, to cause the -direction or management of such entity, whether by contract or -otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity -exercising permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, -including but not limited to software source code, documentation -source, and configuration files. - -"Object" form shall mean any form resulting from mechanical -transformation or translation of a Source form, including but -not limited to compiled object code, generated documentation, -and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or -Object form, made available under the License, as indicated by a -copyright notice that is included in or attached to the work -(an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object -form, that is based on (or derived from) the Work and for which the -editorial revisions, annotations, elaborations, or other modifications -represent, as a whole, an original work of authorship. For the purposes -of this License, Derivative Works shall not include works that remain -separable from, or merely link (or bind by name) to the interfaces of, -the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including -the original version of the Work and any modifications or additions -to that Work or Derivative Works thereof, that is intentionally -submitted to Licensor for inclusion in the Work by the copyright owner -or by an individual or Legal Entity authorized to submit on behalf of -the copyright owner. For the purposes of this definition, "submitted" -means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, -and issue tracking systems that are managed by, or on behalf of, the -Licensor for the purpose of discussing and improving the Work, but -excluding communication that is conspicuously marked or otherwise -designated in writing by the copyright owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity -on behalf of whom a Contribution has been received by Licensor and -subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of -this License, each Contributor hereby grants to You a perpetual, -worldwide, non-exclusive, no-charge, royalty-free, irrevocable -copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the -Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of -this License, each Contributor hereby grants to You a perpetual, -worldwide, non-exclusive, no-charge, royalty-free, irrevocable -(except as stated in this section) patent license to make, have made, -use, offer to sell, sell, import, and otherwise transfer the Work, -where such license applies only to those patent claims licensable -by such Contributor that are necessarily infringed by their -Contribution(s) alone or by combination of their Contribution(s) -with the Work to which such Contribution(s) was submitted. If You -institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work -or a Contribution incorporated within the Work constitutes direct -or contributory patent infringement, then any patent licenses -granted to You under this License for that Work shall terminate -as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the -Work or Derivative Works thereof in any medium, with or without -modifications, and in Source or Object form, provided that You -meet the following conditions: - -(a) You must give any other recipients of the Work or -Derivative Works a copy of this License; and - -(b) You must cause any modified files to carry prominent notices -stating that You changed the files; and - -(c) You must retain, in the Source form of any Derivative Works -that You distribute, all copyright, patent, trademark, and -attribution notices from the Source form of the Work, -excluding those notices that do not pertain to any part of -the Derivative Works; and - -(d) If the Work includes a "NOTICE" text file as part of its -distribution, then any Derivative Works that You distribute must -include a readable copy of the attribution notices contained -within such NOTICE file, excluding those notices that do not -pertain to any part of the Derivative Works, in at least one -of the following places: within a NOTICE text file distributed -as part of the Derivative Works; within the Source form or -documentation, if provided along with the Derivative Works; or, -within a display generated by the Derivative Works, if and -wherever such third-party notices normally appear. The contents -of the NOTICE file are for informational purposes only and -do not modify the License. You may add Your own attribution -notices within Derivative Works that You distribute, alongside -or as an addendum to the NOTICE text from the Work, provided -that such additional attribution notices cannot be construed -as modifying the License. - -You may add Your own copyright statement to Your modifications and -may provide additional or different license terms and conditions -for use, reproduction, or distribution of Your modifications, or -for any such Derivative Works as a whole, provided Your use, -reproduction, and distribution of the Work otherwise complies with -the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, -any Contribution intentionally submitted for inclusion in the Work -by You to the Licensor shall be under the terms and conditions of -this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify -the terms of any separate license agreement you may have executed -with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade -names, trademarks, service marks, or product names of the Licensor, -except as required for reasonable and customary use in describing the -origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or -agreed to in writing, Licensor provides the Work (and each -Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -implied, including, without limitation, any warranties or conditions -of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A -PARTICULAR PURPOSE. You are solely responsible for determining the -appropriateness of using or redistributing the Work and assume any -risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, -whether in tort (including negligence), contract, or otherwise, -unless required by applicable law (such as deliberate and grossly -negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, -incidental, or consequential damages of any character arising as a -result of this License or out of the use or inability to use the -Work (including but not limited to damages for loss of goodwill, -work stoppage, computer failure or malfunction, or any and all -other commercial damages or losses), even if such Contributor -has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing -the Work or Derivative Works thereof, You may choose to offer, -and charge a fee for, acceptance of support, warranty, indemnity, -or other liability obligations and/or rights consistent with this -License. However, in accepting such obligations, You may act only -on Your own behalf and on Your sole responsibility, not on behalf -of any other Contributor, and only if You agree to indemnify, -defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason -of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - -To apply the Apache License to your work, attach the following -boilerplate notice, with the fields enclosed by brackets "[]" -replaced with your own identifying information. (Don't include -the brackets!) The text should be enclosed in the appropriate -comment syntax for the file format. We also recommend that a -file or class name and description of purpose be included on the -same "printed page" as the copyright notice for easier -identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/README.md b/README.md index 08d59ee6..cc68ddb1 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Calculator -The Windows Calculator app is a modern Windows app written in C++ that ships pre-installed with Windows. +The Windows Calculator app is a modern Windows app written in C++ and C# that ships pre-installed with Windows. The app provides standard, scientific, and programmer calculator functionality, as well as a set of converters between various units of measurement and currencies. Calculator ships regularly with new features and bug fixes. You can get the latest version of Calculator in the [Microsoft Store](https://www.microsoft.com/store/apps/9WZDNCRFHVN5). -[![Build Status](https://dev.azure.com/ms/calculator/_apis/build/status/Calculator-CI?branchName=master)](https://dev.azure.com/ms/calculator/_build/latest?definitionId=57&branchName=master) +[![Build Status](https://dev.azure.com/ms/calculator/_apis/build/status/Calculator-CI?branchName=main)](https://dev.azure.com/ms/calculator/_build/latest?definitionId=57&branchName=main) ![Calculator Screenshot](docs/Images/CalculatorScreenshot.png) @@ -22,11 +22,11 @@ Calculator ships regularly with new features and bug fixes. You can get the late ## Getting started Prerequisites: -- Your computer must be running Windows 10, version 1803 or newer. +- Your computer must be running Windows 11, build 22000 or newer. - Install the latest version of [Visual Studio](https://developer.microsoft.com/en-us/windows/downloads) (the free community edition is sufficient). - Install the "Universal Windows Platform Development" workload. - Install the optional "C++ Universal Windows Platform tools" component. - - Install the latest Windows 10 SDK. + - Install the latest Windows 11 SDK. ![Visual Studio Installation Screenshot](docs/Images/VSInstallationScreenshot.png) - Install the [XAML Styler](https://marketplace.visualstudio.com/items?itemName=TeamXavalon.XAMLStyler) Visual Studio extension. diff --git a/build/pipelines/azure-pipelines.ci-internal.yaml b/build/pipelines/azure-pipelines.ci-internal.yaml new file mode 100644 index 00000000..dcfbadaa --- /dev/null +++ b/build/pipelines/azure-pipelines.ci-internal.yaml @@ -0,0 +1,58 @@ +# +# Continuous Integration (CI) - Internal +# This pipeline builds and validate the app for all supported architectures, in a production +# configuration. This pipeline relies on Microsoft-internal resources to run. +# + +trigger: +- main +- release/* +- feature/* +pr: none + +name: 0.$(Date:yyMM).$(DayOfMonth)$(Rev:rr).0 + +jobs: +- template: ./templates/build-single-architecture.yaml + parameters: + isReleaseBuild: true + useReleaseAppxManifest: false + platform: x64 + +- template: ./templates/build-single-architecture.yaml + parameters: + isReleaseBuild: true + useReleaseAppxManifest: false + platform: x86 + +- template: ./templates/build-single-architecture.yaml + parameters: + isReleaseBuild: true + useReleaseAppxManifest: false + platform: ARM + +- template: ./templates/build-single-architecture.yaml + parameters: + isReleaseBuild: true + useReleaseAppxManifest: false + platform: ARM64 + +- template: ./templates/run-ui-tests.yaml + parameters: + platform: x64 + runsettingsFileName: CalculatorUITests.ci-internal.runsettings + +- template: ./templates/run-ui-tests.yaml + parameters: + platform: x86 + runsettingsFileName: CalculatorUITests.ci-internal.runsettings + +- template: ./templates/run-unit-tests.yaml + parameters: + platform: x64 + +- template: ./templates/run-unit-tests.yaml + parameters: + platform: x86 + +- template: ./templates/package-msixbundle.yaml diff --git a/build/pipelines/azure-pipelines.ci.yaml b/build/pipelines/azure-pipelines.ci.yaml index 2d55627a..db8d1849 100644 --- a/build/pipelines/azure-pipelines.ci.yaml +++ b/build/pipelines/azure-pipelines.ci.yaml @@ -1,51 +1,60 @@ # # Continuous Integration (CI) -# This pipeline builds and validate the app in all supported configurations. If the build was -# queued to validate a pull request, we build and test only x64. +# This pipeline builds and validate the app for all supported architectures, in a public +# configuration. If the build was queued to validate a pull request, we build and test only x64. # trigger: -- master +- main - release/* - feature/* pr: -- master +- main - release/* - feature/* name: 0.$(Date:yyMM).$(DayOfMonth)$(Rev:rr).0 jobs: -- template: ./templates/build-app-public.yaml +- template: ./templates/build-single-architecture.yaml parameters: platform: x64 + isOSSBuild: true -- template: ./templates/build-app-public.yaml +- template: ./templates/build-single-architecture.yaml parameters: platform: x86 + isOSSBuild: true condition: not(eq(variables['Build.Reason'], 'PullRequest')) -- template: ./templates/build-app-public.yaml +- template: ./templates/build-single-architecture.yaml parameters: platform: ARM + isOSSBuild: true condition: not(eq(variables['Build.Reason'], 'PullRequest')) -- template: ./templates/build-app-public.yaml +- template: ./templates/build-single-architecture.yaml parameters: platform: ARM64 + isOSSBuild: true condition: not(eq(variables['Build.Reason'], 'PullRequest')) - template: ./templates/run-ui-tests.yaml parameters: platform: x64 + isOSSBuild: true runsettingsFileName: CalculatorUITests.ci.runsettings - template: ./templates/run-unit-tests.yaml parameters: platform: x64 + isOSSBuild: true - template: ./templates/run-unit-tests.yaml parameters: platform: x86 + isOSSBuild: true -- template: ./templates/package-appxbundle.yaml +- template: ./templates/package-msixbundle.yaml + parameters: + isOSSBuild: true diff --git a/build/pipelines/azure-pipelines.loc.yaml b/build/pipelines/azure-pipelines.loc.yaml index af68fef3..880c9b6b 100644 --- a/build/pipelines/azure-pipelines.loc.yaml +++ b/build/pipelines/azure-pipelines.loc.yaml @@ -12,7 +12,7 @@ schedules: displayName: Daily sync branches: include: - - master + - main always: true trigger: none @@ -23,7 +23,7 @@ name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr) jobs: - job: Localize pool: - vmImage: windows-2019 + name: EssentialExperiences-windows-2022 variables: skipComponentGovernanceDetection: true steps: @@ -51,4 +51,4 @@ jobs: condition: eq(variables['hasChanges'], '1') inputs: artifactName: Patch - targetPath: $(Build.ArtifactStagingDirectory) \ No newline at end of file + targetPath: $(Build.ArtifactStagingDirectory) diff --git a/build/pipelines/azure-pipelines.release.yaml b/build/pipelines/azure-pipelines.release.yaml index 8a1328ec..54121b18 100644 --- a/build/pipelines/azure-pipelines.release.yaml +++ b/build/pipelines/azure-pipelines.release.yaml @@ -4,37 +4,43 @@ # Store and the Windows image. This pipeline relies on Microsoft-internal resources to run. # -schedules: -- cron: "0 7 * * *" - displayName: Daily midnight build - branches: - include: - - master - trigger: none pr: none variables: - versionMajor: 10 - versionMinor: 2103 - versionBuild: $[counter('10.2103.*', 0)] + versionMajor: 11 + versionMinor: 2305 + versionBuild: $[counter(format('{0}.{1}.*', variables['versionMajor'], variables['versionMinor']), 0)] versionPatch: 0 name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)' jobs: -- template: ./templates/build-app-internal.yaml +- template: ./templates/build-single-architecture.yaml parameters: platform: x64 + isReleaseBuild: true + useReleaseAppxmanifest: true -- template: ./templates/build-app-internal.yaml +- template: ./templates/build-single-architecture.yaml parameters: platform: x86 + isReleaseBuild: true + useReleaseAppxmanifest: true condition: not(eq(variables['Build.Reason'], 'PullRequest')) -- template: ./templates/build-app-internal.yaml +- template: ./templates/build-single-architecture.yaml parameters: platform: ARM + isReleaseBuild: true + useReleaseAppxmanifest: true + condition: not(eq(variables['Build.Reason'], 'PullRequest')) + +- template: ./templates/build-single-architecture.yaml + parameters: + platform: ARM64 + isReleaseBuild: true + useReleaseAppxmanifest: true condition: not(eq(variables['Build.Reason'], 'PullRequest')) - template: ./templates/run-ui-tests.yaml @@ -55,8 +61,10 @@ jobs: parameters: platform: x86 -- template: ./templates/package-appxbundle.yaml +- template: ./templates/package-msixbundle.yaml parameters: signBundle: true + createStoreBrokerPackages: true -- template: ./templates/prepare-release-internalonly.yaml +- template: ./templates/release-store.yaml +- template: ./templates/release-vpack.yaml diff --git a/build/pipelines/templates/build-app-internal.yaml b/build/pipelines/templates/build-app-internal.yaml deleted file mode 100644 index 9e082815..00000000 --- a/build/pipelines/templates/build-app-internal.yaml +++ /dev/null @@ -1,65 +0,0 @@ -# This template contains a job to build the app for a single architecture and run static analysis -# tools on the binaries. -# The app is built in a production configuration to be released to the Store and the Windows image. -# This job relies on Microsoft-internal resources to run. - -parameters: - platform: '' - condition: '' - -jobs: -- job: Build${{ parameters.platform }} - displayName: Build ${{ parameters.platform }} - condition: ${{ parameters.condition }} - pool: - vmImage: windows-2019 - variables: - BuildConfiguration: Release - BuildPlatform: ${{ parameters.platform }} - steps: - - checkout: self - fetchDepth: 1 - - - task: UniversalPackages@0 - displayName: Download internals package - inputs: - command: download - downloadDirectory: $(Build.SourcesDirectory) - vstsFeed: WindowsInboxApps - vstsFeedPackage: calculator-internals - vstsPackageVersion: 0.0.54 - - - template: ./build-single-architecture.yaml - parameters: - extraMsBuildArgs: '/p:IsStoreBuild=true' - - - task: PublishSymbols@2 - displayName: Publish symbols - inputs: - symbolsFolder: $(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform) - searchPattern: '**/*.pdb' - symbolServerType: teamServices - treatNotIndexedAsWarning: true - symbolsArtifactName: $(System.teamProject)/$(Build.BuildNumber)_$(BuildPlatform)$(BuildConfiguration) - - - task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@3 - displayName: Run BinSkim - inputs: - inputType: Basic - analyzeTarget: $(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator\* - analyzeVerbose: true - analyzeHashes: true - continueOnError: true - - - task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@1 - displayName: Run PoliCheck - inputs: - targetType: F - - - task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@2 - displayName: Publish security analysis logs - - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: Detect open source components - inputs: - sourceScanPath: $(Agent.BuildDirectory) diff --git a/build/pipelines/templates/build-app-public.yaml b/build/pipelines/templates/build-app-public.yaml deleted file mode 100644 index 70f18e5b..00000000 --- a/build/pipelines/templates/build-app-public.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# This template contains a job to build the app for a single architecture. -# Only the contents of the public repository are built; internal resources are not used. - -parameters: - platform: '' - condition: '' - -jobs: -- job: Build${{ parameters.platform }} - displayName: Build ${{ parameters.platform }} - condition: ${{ parameters.condition }} - pool: - vmImage: windows-2019 - variables: - BuildConfiguration: Release - BuildPlatform: ${{ parameters.platform }} - steps: - - checkout: self - fetchDepth: 1 - - - template: ./build-single-architecture.yaml \ No newline at end of file diff --git a/build/pipelines/templates/build-single-architecture.yaml b/build/pipelines/templates/build-single-architecture.yaml index 49056df1..faddea26 100644 --- a/build/pipelines/templates/build-single-architecture.yaml +++ b/build/pipelines/templates/build-single-architecture.yaml @@ -1,18 +1,58 @@ -# This template contains steps to build the app for a single architecture. -# The job containing these steps must set the variables 'BuildConfiguration' and 'BuildPlatform'. +# This template contains a job to build the app for a single architecture. parameters: - extraMsBuildArgs: '' + isReleaseBuild: false + isOSSBuild: false + useReleaseAppxManifest: false + platform: '' + condition: '' + +jobs: +- job: Build${{ parameters.platform }} + displayName: Build ${{ parameters.platform }} + condition: ${{ parameters.condition }} + pool: + ${{ if eq(parameters.isOSSBuild, true) }}: + name: EssentialExperiencesOpenSource-windows-2022 + ${{ if eq(parameters.isOSSBuild, false) }}: + name: EssentialExperiences-windows-2022 + variables: + BuildConfiguration: Release + BuildPlatform: ${{ parameters.platform }} + ${{ if eq(parameters.isReleaseBuild, true) }}: + ${{ if eq(parameters.useReleaseAppxManifest, true) }}: + ExtraMSBuildArgs: '/p:IsStoreBuild=true /p:UseReleaseAppxManifest=true' + ${{ if eq(parameters.useReleaseAppxManifest, false) }}: + ExtraMSBuildArgs: '/p:IsStoreBuild=true' + ${{ if eq(parameters.isReleaseBuild, false) }}: + ${{ if eq(parameters.useReleaseAppxManifest, true) }}: + ExtraMSBuildArgs: '/p:UseReleaseAppxManifest=true' + ${{ if eq(parameters.useReleaseAppxManifest, false) }}: + ExtraMSBuildArgs: '' + ${{ if eq(parameters.useReleaseAppxManifest, false) }}: + ManifestFileName: 'Package.appxmanifest' + ${{ if eq(parameters.useReleaseAppxManifest, true) }}: + ManifestFileName: 'Package.Release.appxmanifest' + steps: + - checkout: self + fetchDepth: 1 + + - ${{ if eq(parameters.isReleaseBuild, true) }}: + - task: UniversalPackages@0 + displayName: Download internals package + inputs: + command: download + downloadDirectory: $(Build.SourcesDirectory) + vstsFeed: WindowsInboxApps + vstsFeedPackage: calculator-internals + vstsPackageVersion: 0.0.105 -steps: - task: NuGetToolInstaller@1 - displayName: Use NuGet 5.x + displayName: Use NuGet 6.x inputs: - versionSpec: 5.x + versionSpec: 6.x - # In most accounts, you can just use 'NuGetCommand' instead of this GUID. - # In the microsoft.visualstudio.com account, NuGetCommand is ambiguous so the GUID is needed. - - task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 + - task: NuGetCommand@2 displayName: NuGet restore src/Calculator.sln inputs: command: custom @@ -22,21 +62,82 @@ steps: displayName: Set version number in AppxManifest inputs: filePath: $(Build.SourcesDirectory)\build\scripts\UpdateAppxManifestVersion.ps1 - arguments: '-AppxManifest $(Build.SourcesDirectory)\src\Calculator\Package.appxmanifest -Version $(Build.BuildNumber)' + arguments: '-AppxManifest $(Build.SourcesDirectory)\src\Calculator\$(ManifestFileName) -Version $(Build.BuildNumber)' - task: VSBuild@1 displayName: 'Build solution src/Calculator.sln' inputs: solution: src/Calculator.sln - vsVersion: 16.0 - msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:AppVersion=$(Build.BuildNumber) /t:Publish /p:PublishDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\publish\ ${{ parameters.extraMsBuildArgs }} + vsVersion: 17.0 + msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:Version=$(Build.BuildNumber) /t:Publish /p:PublishDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\publish\ $(ExtraMSBuildArgs) platform: $(BuildPlatform) configuration: $(BuildConfiguration) maximumCpuCount: true + - ${{ if eq(parameters.isReleaseBuild, true) }}: + - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 + displayName: 'Generate Software Bill of Material(SBoM)' + inputs: + BuildDropPath: $(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator + PackageName: 'Microsoft.WindowsCalculator' + PackageVersion: $(Build.BuildNumber) + - task: PublishBuildArtifacts@1 displayName: Publish drop artifact inputs: artifactName: drop pathToPublish: $(Build.BinariesDirectory) parallel: true + + - ${{ if eq(parameters.isReleaseBuild, true) }}: + - task: PublishSymbols@2 + displayName: Publish symbols + inputs: + symbolsFolder: $(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform) + searchPattern: '**/*.pdb' + symbolServerType: teamServices + treatNotIndexedAsWarning: true + symbolsArtifactName: $(System.teamProject)/$(Build.BuildNumber)_$(BuildPlatform)$(BuildConfiguration) + + - task: CopyFiles@2 + displayName: Copy Files for BinSkim analysis + inputs: + SourceFolder: '$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator\' + # Setting up a folder to store all the binary files that we need BinSkim to scan. + # If we put more things than we produce pdbs for and can index (such as nuget packages that ship without pdbs), binskim will fail. + # Below are ignored files + # - clrcompression.dll + # - WebView2Loader.dll + # - Microsoft.Web.WebView2.Core.dll + Contents: | + **\* + !**\clrcompression.dll + !**\WebView2Loader.dll + !**\Microsoft.Web.WebView2.Core.dll + TargetFolder: '$(Agent.BuildDirectory)\binskim' + CleanTargetFolder: true + OverWrite: true + flattenFolders: false + analyzeTarget: '$(Agent.BuildDirectory)\binskim\*' + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@3 + displayName: Run BinSkim + inputs: + inputType: Basic + analyzeTarget: '$(Agent.BuildDirectory)\binskim\*' + analyzeVerbose: true + analyzeHashes: true + continueOnError: true + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@1 + displayName: Run PoliCheck + inputs: + targetType: F + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@2 + displayName: Publish security analysis logs + + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: Detect open source components + inputs: + sourceScanPath: $(Agent.BuildDirectory) diff --git a/build/pipelines/templates/package-appxbundle.yaml b/build/pipelines/templates/package-appxbundle.yaml deleted file mode 100644 index f8de83ce..00000000 --- a/build/pipelines/templates/package-appxbundle.yaml +++ /dev/null @@ -1,101 +0,0 @@ -# This template contains a job which takes .appx packages which were built separately for each -# architecture (arm, x86, etc.) and combines them into a single .appxbundle. - -parameters: - signBundle: false - -jobs: -- job: Package - dependsOn: - - Buildx64 - - Buildx86 - - BuildARM - condition: | - and - ( - in(dependencies.Buildx64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), - in(dependencies.Buildx86.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), - in(dependencies.BuildARM.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') - ) - pool: - vmImage: windows-2019 - variables: - skipComponentGovernanceDetection: true - steps: - - checkout: self - fetchDepth: 1 - - - task: DownloadBuildArtifacts@0 - displayName: Download all .appx artifacts - inputs: - artifactName: drop - itemPattern: '**/*.appx' - - - task: PowerShell@2 - displayName: Generate AppxBundle mapping - inputs: - filePath: $(Build.SourcesDirectory)\build\scripts\CreateAppxBundleMapping.ps1 - arguments: '-InputPath $(Build.ArtifactStagingDirectory)\drop\Release -ProjectName Calculator -OutputFile $(Build.BinariesDirectory)\AppxBundleMapping.txt' - - - powershell: | - $buildVersion = [version]$Env:BUILDVERSION - $bundleVersion = "2020.$($buildVersion.Minor).$($buildVersion.Build).$($buildVersion.Revision)" - & "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x86\MakeAppx.exe" bundle /v /bv $bundleVersion /f $Env:MAPPINGFILEPATH /p $Env:OUTPUTPATH - displayName: Make AppxBundle - env: - BUILDVERSION: $(Build.BuildNumber) - MAPPINGFILEPATH: $(Build.BinariesDirectory)\AppxBundleMapping.txt - OUTPUTPATH: $(Build.BinariesDirectory)\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle - - - task: CopyFiles@2 - displayName: Copy AppxBundle to staging directory - inputs: - sourceFolder: $(Build.BinariesDirectory) - contents: Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle - targetFolder: $(Build.ArtifactStagingDirectory)\appxBundle - - - task: PublishBuildArtifacts@1 - displayName: Publish AppxBundle artifact - inputs: - artifactName: appxBundle - pathToPublish: $(Build.ArtifactStagingDirectory)\appxBundle - - - ${{ if eq(parameters.signBundle, true) }}: - - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 - displayName: Send appxbundle to code signing service - inputs: - ConnectedServiceName: Essential Experiences Codesign - FolderPath: $(Build.ArtifactStagingDirectory)\appxBundle - Pattern: Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "CertTemplateName": "WINMSAPP1ST", - "CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", - "KeyCode": "Dynamic", - "OperationCode": "SigntoolvNextSign", - "Parameters": { - "OpusName": "Microsoft", - "OpusInfo": "http://www.microsoft.com", - "FileDigest": "/fd \"SHA256\"", - "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - }, - "ToolName": "sign", - "ToolVersion": "1.0" - }, - { - "CertTemplateName": "WINMSAPP1ST", - "CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", - "KeyCode": "Dynamic", - "OperationCode": "SigntoolvNextVerify", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - } - ] - - task: PublishBuildArtifacts@1 - displayName: Publish AppxBundleSigned artifact - inputs: - pathtoPublish: $(Build.ArtifactStagingDirectory)\appxBundle - artifactName: appxBundleSigned \ No newline at end of file diff --git a/build/pipelines/templates/package-msixbundle.yaml b/build/pipelines/templates/package-msixbundle.yaml new file mode 100644 index 00000000..0ca7509e --- /dev/null +++ b/build/pipelines/templates/package-msixbundle.yaml @@ -0,0 +1,160 @@ +# This template contains a job which takes .msix packages which were built separately for each +# architecture (arm, x86, etc.) and combines them into a single .msixbundle. In release builds, +# this job also signs the bundle and creates StoreBroker packages. + +parameters: + isOSSBuild: false + signBundle: false + createStoreBrokerPackages: false + +jobs: +- job: Package + dependsOn: + - Buildx64 + - Buildx86 + - BuildARM + - BuildARM64 + condition: | + and + ( + in(dependencies.Buildx64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), + in(dependencies.Buildx86.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), + in(dependencies.BuildARM.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'), + in(dependencies.BuildARM64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped') + ) + pool: + ${{ if eq(parameters.isOSSBuild, true) }}: + name: EssentialExperiencesOpenSource-windows-2022 + ${{ if eq(parameters.isOSSBuild, false) }}: + name: EssentialExperiences-windows-2022 + variables: + skipComponentGovernanceDetection: true + StoreBrokerMediaRootPath: $(TEMP)\SBMedia + StoreBrokerPackagePath: $(Build.ArtifactStagingDirectory)\storeBrokerPayload + steps: + - checkout: self + fetchDepth: 1 + + - task: DownloadBuildArtifacts@0 + displayName: Download all .msix artifacts + inputs: + artifactName: drop + itemPattern: '**/*.msix' + + - ${{ if eq(parameters.createStoreBrokerPackages, true) }}: + - task: UniversalPackages@0 + displayName: Download internals package + inputs: + command: download + downloadDirectory: $(Build.SourcesDirectory) + vstsFeed: WindowsInboxApps + vstsFeedPackage: calculator-internals + vstsPackageVersion: 0.0.105 + + - task: PowerShell@2 + displayName: Generate MsixBundle mapping + inputs: + filePath: $(Build.SourcesDirectory)\build\scripts\CreateMsixBundleMapping.ps1 + arguments: '-InputPath $(Build.ArtifactStagingDirectory)\drop\Release -ProjectName Calculator -OutputFile $(Build.BinariesDirectory)\MsixBundleMapping.txt' + + - powershell: | + $buildVersion = [version]$Env:BUILDVERSION + $bundleVersion = "2021.$($buildVersion.Minor).$($buildVersion.Build).$($buildVersion.Revision)" + & "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\MakeAppx.exe" bundle /v /bv $bundleVersion /f $Env:MAPPINGFILEPATH /p $Env:OUTPUTPATH + displayName: Make MsixBundle + env: + BUILDVERSION: $(Build.BuildNumber) + MAPPINGFILEPATH: $(Build.BinariesDirectory)\MsixBundleMapping.txt + OUTPUTPATH: $(Build.BinariesDirectory)\Microsoft.WindowsCalculator_8wekyb3d8bbwe.msixbundle + + - task: CopyFiles@2 + displayName: Copy MsixBundle to staging directory + inputs: + sourceFolder: $(Build.BinariesDirectory) + contents: Microsoft.WindowsCalculator_8wekyb3d8bbwe.msixbundle + targetFolder: $(Build.ArtifactStagingDirectory)\msixBundle + + - task: PublishBuildArtifacts@1 + displayName: Publish MsixBundle artifact + inputs: + artifactName: msixBundle + pathToPublish: $(Build.ArtifactStagingDirectory)\msixBundle + + - ${{ if eq(parameters.signBundle, true) }}: + - task: EsrpCodeSigning@2 + displayName: Send msixbundle to code signing service + inputs: + ConnectedServiceName: Essential Experiences Codesign + FolderPath: $(Build.ArtifactStagingDirectory)\msixBundle + Pattern: Microsoft.WindowsCalculator_8wekyb3d8bbwe.msixbundle + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "CertTemplateName": "WINMSAPP1ST", + "CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", + "KeyCode": "Dynamic", + "OperationCode": "SigntoolvNextSign", + "Parameters": { + "OpusName": "Microsoft", + "OpusInfo": "http://www.microsoft.com", + "FileDigest": "/fd \"SHA256\"", + "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + }, + "ToolName": "sign", + "ToolVersion": "1.0" + }, + { + "CertTemplateName": "WINMSAPP1ST", + "CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", + "KeyCode": "Dynamic", + "OperationCode": "SigntoolvNextVerify", + "Parameters": {}, + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + - task: PublishBuildArtifacts@1 + displayName: Publish MsixBundleSigned artifact + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory)\msixBundle + artifactName: msixBundleSigned + + - ${{ if eq(parameters.createStoreBrokerPackages, true) }}: + - powershell: | + # Just modify this line to indicate where your en-us PDP file is. Leave the other lines alone. + $enUSPdpFilePath = "$(Build.SourcesDirectory)\PDP\en-US\PDP.xml" + + # This is going to save the release value from the PDP file to $(SBMediaReleaseVersion) + # which you can then refer to in the UniversalPackages task. + $release = ([xml](Get-Content $enUSPdpFilePath)).ProductDescription.Release.Trim() + Write-Host "##vso[task.setvariable variable=SBMediaReleaseVersion;]$release" + displayName: Determine the PDP Media release version from the en-us PDP file + + - task: UniversalPackages@0 + displayName: Download PDP media (screenshots, trailers) universal package + inputs: + command: download + downloadDirectory: $(StoreBrokerMediaRootPath)/$(SBMediaReleaseVersion) + vstsFeed: WindowsInboxApps + vstsFeedPackage: calculator-pdp-media + vstsPackageVersion: $(SBMediaReleaseVersion) + + - task: MS-RDX-MRO.windows-store-publish-dev.package-task.store-package@2 + displayName: Create StoreBroker Payload + inputs: + serviceEndpoint: Calculator StoreBroker Connection + sbConfigPath: Tools/Build/StoreBroker/SBCalculatorConfig.json + sourceFolder: $(Build.ArtifactStagingDirectory)/msixBundle + contents: Microsoft.WindowsCalculator_8wekyb3d8bbwe.msixbundle + pdpPath: $(Build.SourcesDirectory)\PDP + pdpInclude: PDP.xml + pdpMediaPath: $(StoreBrokerMediaRootPath) + outSBPackagePath: $(StoreBrokerPackagePath) + outSBName: SBCalculator + + - task: PublishBuildArtifacts@1 + displayName: Publish StoreBroker Payload artifact + inputs: + pathtoPublish: $(StoreBrokerPackagePath) + artifactName: storeBrokerPayload diff --git a/build/pipelines/templates/prepare-release-internalonly.yaml b/build/pipelines/templates/prepare-release-internalonly.yaml deleted file mode 100644 index cf25aee2..00000000 --- a/build/pipelines/templates/prepare-release-internalonly.yaml +++ /dev/null @@ -1,156 +0,0 @@ -# This template contains a job which builds artifacts needed to release the app to the store and to -# Windows using Microsoft-internal systems. It relies on Microsoft-internal resources and will not -# work outside of Microsoft. -# Specifically, this job: -# - Builds VPacks for including the app in the Windows OS build. Azure DevOps Universal Packages -# offers similar capabilities. -# - Creates StoreBroker packages containing Microsoft Store assets. Although the Store assets for -# this app are not open source, the StoreBroker tool is available at -# https://github.com/Microsoft/StoreBroker. - -jobs: -- job: WindowsInternalRelease - dependsOn: Package - pool: - name: Package ES Standard Build - workspace: - clean: outputs - variables: - skipComponentGovernanceDetection: true - SBMediaRootPath: '$(TEMP)\SBMedia' - SBPackagePath: '$(Build.ArtifactStagingDirectory)\storeBrokerPayload' - SBLogPath: '$(SBPackagePath)\StoreBroker.log' - FlightId: '161f0975-cb5f-475b-8ef6-26383c37621f' - AppId: '9WZDNCRFHVN5' - ProductId: '00009007199266248474' - steps: - - checkout: self - clean: true - - # This must be the first task in the job definition, since it modifies the build environment - # in ways other tasks would not expect (for example, it clears the artifacts directory). - - task: PkgESSetupBuild@10 - displayName: Initialize Package ES - inputs: - productName: Calculator - disableWorkspace: true - useDfs: false - env: - XES_DISABLEPROV: true - - - task: NuGetToolInstaller@1 - displayName: Use NuGet 5.x - inputs: - versionSpec: 5.x - - - task: DownloadBuildArtifacts@0 - displayName: Download appxBundleSigned artifact - inputs: - artifactName: appxBundleSigned - - - task: CopyFiles@2 - displayName: Copy signed AppxBundle to vpack staging folder - inputs: - sourceFolder: $(Build.ArtifactStagingDirectory)\appxBundleSigned - contents: Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle - targetFolder: $(Build.ArtifactStagingDirectory)\vpack\appxBundle - - - task: PkgESVPack@10 - displayName: Create and push vpack for app - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - sourceDirectory: $(Build.ArtifactStagingDirectory)\vpack\appxBundle - description: VPack for the Calculator Application - pushPkgName: calculator.app - version: $(versionMajor).$(versionMinor).$(versionBuild) - owner: paxeeapps - provData: false - - - - task: PublishBuildArtifacts@1 - displayName: Publish vpack\app artifact with vpack manifest - inputs: - pathtoPublish: $(XES_VPACKMANIFESTDIRECTORY)\$(XES_VPACKMANIFESTNAME) - artifactName: vpack\app - - - task: UniversalPackages@0 - displayName: Download internals package - inputs: - command: download - downloadDirectory: $(Build.SourcesDirectory) - vstsFeed: WindowsInboxApps - vstsFeedPackage: calculator-internals - vstsPackageVersion: 0.0.54 - - - powershell: | - # Just modify this line to indicate where your en-us PDP file is. Leave the other lines alone. - $enUSPdpFilePath = "$(Build.SourcesDirectory)\PDP\en-US\PDP.xml" - - # This is going to save the release value from the PDP file to $(SBMediaReleaseVersion) - # which you can then refer to in the UniversalPackages task. - $release = ([xml](Get-Content $enUSPdpFilePath)).ProductDescription.Release.Trim() - Write-Host "##vso[task.setvariable variable=SBMediaReleaseVersion;]$release" - displayName: Determine the PDP Media release version from the en-us PDP file - - - task: UniversalPackages@0 - displayName: Download PDP media (screenshots, trailers) universal package - inputs: - command: download - downloadDirectory: $(SBMediaRootPath)/$(SBMediaReleaseVersion) - vstsFeed: WindowsInboxApps - vstsFeedPackage: calculator-pdp-media - vstsPackageVersion: $(SBMediaReleaseVersion) - - - task: MS-RDX-MRO.windows-store-publish-dev.package-task.store-package@2 - displayName: Create StoreBroker Payload - inputs: - serviceEndpoint: Essential Experiences StoreBrokerProxy - sbConfigPath: Tools/Build/StoreBroker/SBCalculatorConfig.json - sourceFolder: $(Build.ArtifactStagingDirectory)/appxBundleSigned - contents: Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle - pdpPath: '$(Build.SourcesDirectory)\PDP' - pdpInclude: PDP.xml - pdpMediaPath: '$(SBMediaRootPath)' - outSBPackagePath: '$(SBPackagePath)' - outSBName: SBCalculator - - - task: PublishBuildArtifacts@1 - displayName: Publish StoreBroker Payload artifact - inputs: - pathtoPublish: '$(SBPackagePath)' - artifactName: storeBrokerPayload - - - task: MS-RDX-MRO.windows-store-publish-dev.flight-task.store-flight@2 - displayName: 'Flight StoreBroker Payload to team ring' - name: StoreBrokerFlight - inputs: - serviceEndpoint: Essential Experiences StoreBrokerProxy - appId: '$(AppId)' - flightId: '$(FlightId)' - inputMethod: JsonAndZip - jsonPath: '$(SBPackagePath)\SBCalculator.json' - zipPath: '$(SBPackagePath)\SBCalculator.zip' - force: true - skipPolling: true - targetPublishMode: Immediate - logPath: '$(SBLogPath)' - deletePackages: true - numberOfPackagesToKeep: 0 - - - task: PkgESStoreBrokerAeroUpload@10 - displayName: Upload to Aero flighting dashboard - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - inputs: - ProductId: '$(ProductId)' - FlightId: '$(FlightId)' - SubmissionId: '$(StoreBrokerFlight.WS_SubmissionId)' - SubmissionDataPath: '$(SBPackagePath)\SBCalculator.json' - PackagePath: '$(SBPackagePath)\SBCalculator.zip' - AeroEnvironment: Production - - - task: PkgESLateTasks@10 - displayName: Run PackageES LateTasks - env: - XES_DISABLEPROV: true diff --git a/build/pipelines/templates/release-store.yaml b/build/pipelines/templates/release-store.yaml new file mode 100644 index 00000000..551662ca --- /dev/null +++ b/build/pipelines/templates/release-store.yaml @@ -0,0 +1,48 @@ +# This template contains jobs to release the app to the Store. + +jobs: +- job: ReleaseStore + dependsOn: Package + pool: + name: EssentialExperiences-windows-2022 + variables: + skipComponentGovernanceDetection: true + StoreBrokerPackagePath: $(Build.ArtifactStagingDirectory)\storeBrokerPayload + StoreBrokerLogPath: $(StoreBrokerPackagePath)\StoreBroker.log + FlightId: 161f0975-cb5f-475b-8ef6-26383c37621f + AppId: 9WZDNCRFHVN5 + ProductId: 00009007199266248474 + steps: + - checkout: none + + - task: DownloadBuildArtifacts@0 + displayName: Download storeBrokerPayload artifact + inputs: + artifactName: storeBrokerPayload + + - task: MS-RDX-MRO.windows-store-publish-dev.flight-task.store-flight@2 + displayName: Flight StoreBroker Payload to team ring + name: StoreBrokerFlight + inputs: + serviceEndpoint: Calculator StoreBroker Connection + appId: $(AppId) + flightId: $(FlightId) + inputMethod: JsonAndZip + jsonPath: $(StoreBrokerPackagePath)\SBCalculator.json + zipPath: $(StoreBrokerPackagePath)\SBCalculator.zip + force: true + skipPolling: true + targetPublishMode: Immediate + logPath: $(StoreBrokerLogPath) + deletePackages: true + numberOfPackagesToKeep: 0 + + - task: APS-Aero-Package.aero-upload-task.AeroUploadTask.AeroUpload@0 + displayName: Aero Upload + inputs: + productId: $(ProductId) + flightId: $(FlightId) + submissionId: $(StoreBrokerFlight.WS_SubmissionId) + submissionDataPath: $(StoreBrokerPackagePath)\SBCalculator.json + packagePath: $(StoreBrokerPackagePath)\SBCalculator.zip + serviceEndpoint: AeroUpload-APS-Calculator \ No newline at end of file diff --git a/build/pipelines/templates/release-vpack.yaml b/build/pipelines/templates/release-vpack.yaml new file mode 100644 index 00000000..2de88a81 --- /dev/null +++ b/build/pipelines/templates/release-vpack.yaml @@ -0,0 +1,42 @@ +# This template contains a job to create a VPack. The VPack is used to preinstall the app in a +# Windows OS build. + +jobs: +- job: ReleaseVPack + dependsOn: Package + pool: + name: EssentialExperiences-windows-2022 + variables: + skipComponentGovernanceDetection: true + steps: + - checkout: none + + - task: DownloadBuildArtifacts@0 + displayName: Download msixBundleSigned artifact + inputs: + artifactName: msixBundleSigned + + - task: CopyFiles@2 + displayName: Copy signed MsixBundle to vpack staging folder + inputs: + sourceFolder: $(Build.ArtifactStagingDirectory)\msixBundleSigned + contents: Microsoft.WindowsCalculator_8wekyb3d8bbwe.msixbundle + targetFolder: $(Build.ArtifactStagingDirectory)\vpack\msixBundle + + - task: PkgESVPack@12 + displayName: Create and push vpack for app + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + inputs: + sourceDirectory: $(Build.ArtifactStagingDirectory)\vpack\msixBundle + description: VPack for the Calculator Application + pushPkgName: calculator.app + version: $(versionMajor).$(versionMinor).$(versionBuild) + owner: paxeeapps + provData: true + + - task: PublishBuildArtifacts@1 + displayName: Publish vpack\app artifact with vpack manifest + inputs: + pathtoPublish: $(XES_VPACKMANIFESTDIRECTORY)\$(XES_VPACKMANIFESTNAME) + artifactName: vpackManifest diff --git a/build/pipelines/templates/run-ui-tests.yaml b/build/pipelines/templates/run-ui-tests.yaml index 347a3a8b..960fb134 100644 --- a/build/pipelines/templates/run-ui-tests.yaml +++ b/build/pipelines/templates/run-ui-tests.yaml @@ -1,6 +1,7 @@ # This template contains jobs to run UI tests using WinAppDriver. parameters: + isOSSBuild: false platform: '' runsettingsFileName: '' @@ -10,18 +11,30 @@ jobs: dependsOn: Build${{ parameters.platform }} condition: succeeded() pool: - vmImage: windows-2019 + ${{ if eq(parameters.isOSSBuild, true) }}: + name: EssentialExperiencesOpenSource-Win11 + ${{ if eq(parameters.isOSSBuild, false) }}: + name: EssentialExperiences-Win11 variables: skipComponentGovernanceDetection: true steps: - - checkout: none + - checkout: self + fetchDepth: 1 - - powershell: Set-DisplayResolution -Width 1920 -Height 1080 -Force - displayName: Set resolution to 1920x1080 - continueOnError: true + - task: PowerShell@2 + displayName: Turn off animation effects + inputs: + filePath: $(Build.SourcesDirectory)\build\scripts\TurnOffAnimationEffects.ps1 + + - task: ScreenResolutionUtility@1 + displayName: Set resolution to 1920x1080 + inputs: + displaySettings: 'specific' + width: 1920 + height: 1080 - task: DownloadBuildArtifacts@0 - displayName: Download AppxBundle and CalculatorUITests + displayName: Download MsixBundle and CalculatorUITests inputs: artifactName: drop itemPattern: | @@ -44,9 +57,8 @@ jobs: displayName: Run CalculatorUITests inputs: testAssemblyVer2: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/CalculatorUITests.dll - vsTestVersion: 16.0 runSettingsFile: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/${{ parameters.runsettingsFileName }} platform: ${{ parameters.platform }} configuration: Release ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: - testFiltercriteria: Priority=0 + testFiltercriteria: Priority=0 diff --git a/build/pipelines/templates/run-unit-tests.yaml b/build/pipelines/templates/run-unit-tests.yaml index 56f60969..6411e243 100644 --- a/build/pipelines/templates/run-unit-tests.yaml +++ b/build/pipelines/templates/run-unit-tests.yaml @@ -1,6 +1,7 @@ # This template contains jobs to run unit tests. parameters: + isOSSBuild: false platform: '' runsettingsFileName: '' @@ -10,7 +11,10 @@ jobs: dependsOn: Build${{ parameters.platform }} condition: succeeded() pool: - vmImage: windows-2019 + ${{ if eq(parameters.isOSSBuild, true) }}: + name: EssentialExperiencesOpenSource-windows-2022 + ${{ if eq(parameters.isOSSBuild, false) }}: + name: EssentialExperiences-windows-2022 variables: skipComponentGovernanceDetection: true steps: @@ -31,5 +35,5 @@ jobs: - task: VSTest@2 displayName: Run CalculatorUnitTests inputs: - testAssemblyVer2: $(Build.ArtifactStagingDirectory)\drop\Release\${{ parameters.platform }}\CalculatorUnitTests\AppPackages\CalculatorUnitTests_Test\CalculatorUnitTests.appx + testAssemblyVer2: $(Build.ArtifactStagingDirectory)\drop\Release\${{ parameters.platform }}\CalculatorUnitTests\AppPackages\CalculatorUnitTests_Test\CalculatorUnitTests.msix otherConsoleOptions: /Platform:${{ parameters.platform }} \ No newline at end of file diff --git a/build/scripts/CreateAppxBundleMapping.ps1 b/build/scripts/CreateMsixBundleMapping.ps1 similarity index 78% rename from build/scripts/CreateAppxBundleMapping.ps1 rename to build/scripts/CreateMsixBundleMapping.ps1 index 6a6abc84..2ad53fba 100644 --- a/build/scripts/CreateAppxBundleMapping.ps1 +++ b/build/scripts/CreateMsixBundleMapping.ps1 @@ -10,26 +10,26 @@ ARM\ Project\ AppPackages\ - Project_ARM.appx - Project_scale-100.appx + Project_ARM.msix + Project_scale-100.msix x64\ Project\ AppPackages\ - Project_x64.appx - Project_scale-100.appx + Project_x64.msix + Project_scale-100.msix .PARAMETER InputPath - The path where appx packages to bundle are located. + The path where msix packages to bundle are located. .PARAMETER ProjectName - The folder name within each architecture to search recursively for appx packages. The appx files + The folder name within each architecture to search recursively for msix packages. The msix files must also have the ProjectName in their file names. .PARAMETER OutputFile The path to write the generated mapping file. .EXAMPLE - Create-AppxBundleMapping -InputPath "C:\drop" -ProjectName "CalculatorApp" -OutputFile "C:\Temp\AppxBundleMapping.txt" + Create-MsixBundleMapping -InputPath "C:\drop" -ProjectName "CalculatorApp" -OutputFile "C:\Temp\MsixBundleMapping.txt" #> param( [Parameter(Mandatory)] @@ -45,7 +45,7 @@ param( $OutputFile ) -# List all appx packages by architecture +# List all msix packages by architecture $architectures = @(Get-ChildItem -Path $InputPath -Directory | Foreach-Object Name | Foreach-Object ToLower) if ($architectures.Count -lt 1) { @@ -57,22 +57,22 @@ $packages = @{} foreach ($architecture in $architectures) { $projectPath = [IO.Path]::Combine($InputPath, $architecture, $ProjectName) - $packages[$architecture] = Get-ChildItem -Path $projectPath -Recurse -Filter *$ProjectName*.appx + $packages[$architecture] = Get-ChildItem -Path $projectPath -Recurse -Filter *$ProjectName*.msix if ($packages[$architecture].Count -lt 1) { - throw "No .appx files found for architecture $architecture in $projectPath" + throw "No .msix files found for architecture $architecture in $projectPath" } } -# List appx packages which are common to all architectures +# List msix packages which are common to all architectures $commonPackages = $packages[$defaultArchitecture] foreach ($architecture in $architectures) { $commonPackages = $packages[$architecture] | Where {$commonPackages.Name -Contains $_.Name} } -# List appx packages which are architecture-specific and verify that there is exactly one per +# List msix packages which are architecture-specific and verify that there is exactly one per # architecture. $architectureSpecificPackages = @() if ($architectures.Count -gt 1) diff --git a/build/scripts/TurnOffAnimationEffects.ps1 b/build/scripts/TurnOffAnimationEffects.ps1 new file mode 100644 index 00000000..9cfa1e4a --- /dev/null +++ b/build/scripts/TurnOffAnimationEffects.ps1 @@ -0,0 +1,22 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +<# +.SYNOPSIS + Disables animations on the system. Equivalent to turning off the "Animation effects" setting in the Windows Settings app. +#> + +Add-Type -AssemblyName System.Runtime.WindowsRuntime +$asTaskGeneric = ([System.WindowsRuntimeSystemExtensions].GetMethods() | ? { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' })[0] + +Function WaitForAsyncAction($WinRtTask, $ResultType) { + $asTask = $asTaskGeneric.MakeGenericMethod($ResultType) + $task = $asTask.Invoke($null, @($WinRtTask)) + $task.GetAwaiter().GetResult() +} + +[Windows.UI.ViewManagement.Core.UISettingsController,Windows.UI.ViewManagement.Core,ContentType=WindowsRuntime] | Out-Null + +$controller = WaitForAsyncAction ([Windows.UI.ViewManagement.Core.UISettingsController]::RequestDefaultAsync()) ([Windows.UI.ViewManagement.Core.UISettingsController]) + +$controller.SetAnimationsEnabled($false) diff --git a/docs/ApplicationArchitecture.md b/docs/ApplicationArchitecture.md index 235af889..080963bf 100644 --- a/docs/ApplicationArchitecture.md +++ b/docs/ApplicationArchitecture.md @@ -21,11 +21,11 @@ that build into the final Calculator application. The View layer is contained in the [Calculator project][Calculator folder]. This project contains mostly XAML files and various custom controls that support the UI. [App.xaml][App.xaml] contains many of the [static][StaticResource] and -[theme][ThemeResource] resources that the other XAML files will reference. Its code-behind file, [App.xaml.cpp][App.xaml.cpp], +[theme][ThemeResource] resources that the other XAML files will reference. Its code-behind file, [App.xaml.cs][App.xaml.cs], contains the main entry point to the application. On startup, it navigates to the main page. -```C++ -rootFrame->Navigate(MainPage::typeid, argument) +```C# +rootFrame.Navigate(typeof(MainPage), argument) ``` In Calculator, there is only one concrete [Page][Page] class: [MainPage.xaml][MainPage.xaml]. `MainPage` is the root @@ -166,7 +166,7 @@ instead of regular floating point arithmetic). The interface to this layer is de [Calculator folder]: ../src/Calculator [App.xaml]: ../src/Calculator/App.xaml -[App.xaml.cpp]: ../src/Calculator/App.xaml.cpp +[App.xaml.cs]: ../src/Calculator/App.xaml.cs [StaticResource]: https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/staticresource-markup-extension [ThemeResource]: https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/themeresource-markup-extension [Page]: https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.Page diff --git a/docs/Images/CalculatorScreenshot.png b/docs/Images/CalculatorScreenshot.png old mode 100644 new mode 100755 index a5c32e96..380060f5 Binary files a/docs/Images/CalculatorScreenshot.png and b/docs/Images/CalculatorScreenshot.png differ diff --git a/docs/Images/VSInstallationScreenshot.png b/docs/Images/VSInstallationScreenshot.png index d027e1bb..b2cf5f40 100644 Binary files a/docs/Images/VSInstallationScreenshot.png and b/docs/Images/VSInstallationScreenshot.png differ diff --git a/docs/Roadmap.md b/docs/Roadmap.md index b63378df..b1a72f2b 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -10,9 +10,9 @@ In 2021, the Windows Calculator team is focused on: * Migrating the codebase to C# ([#893](https://github.com/microsoft/calculator/issues/893)) * Releasing infinite-precision engine as standalone package ([#1545](https://github.com/microsoft/calculator/issues/1545)) and adding support for arbitrary expression parsing ([#526](https://github.com/microsoft/calculator/issues/526)) * Adding a settings page ([#596](https://github.com/microsoft/calculator/issues/596)) -* [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) to get started! +* [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/main/docs/NewFeatureProcess.md) to get started! -We welcome contributions of all kinds from the community, but especially those that support the efforts above. Please see our [contributing guidelines](https://github.com/Microsoft/calculator/blob/master/CONTRIBUTING.md) for more information on how to get involved. +We welcome contributions of all kinds from the community, but especially those that support the efforts above. Please see our [contributing guidelines](https://github.com/Microsoft/calculator/blob/main/CONTRIBUTING.md) for more information on how to get involved. ## Releases diff --git a/nuget.config b/nuget.config index 6ef7f342..0b8604f4 100644 --- a/nuget.config +++ b/nuget.config @@ -1,6 +1,11 @@ - + - - - - + + + + + + + + + \ No newline at end of file diff --git a/src/CalcManager/CEngine/History.cpp b/src/CalcManager/CEngine/History.cpp index e002e62a..f45ff090 100644 --- a/src/CalcManager/CEngine/History.cpp +++ b/src/CalcManager/CEngine/History.cpp @@ -143,14 +143,14 @@ void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool isIntegerMode, bool // This is expected to be called when a binary op in the last say 1+2+ is changing to another one say 1+2* (+ changed to *) // It needs to know by this change a Precedence inversion happened. i.e. previous op was lower or equal to its previous op, but the new // one isn't. (Eg. 1*2* to 1*2^). It can add explicit brackets to ensure the precedence is inverted. (Eg. (1*2) ^) -void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntgerMode) +void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntegerMode) { TruncateEquationSzFromIch(m_lastBinOpStartIndex); if (fPrecInvToHigher) { EnclosePrecInversionBrackets(); } - AddBinOpToHistory(nOpCode, isIntgerMode); + AddBinOpToHistory(nOpCode, isIntegerMode); } void CHistoryCollector::PushLastOpndStart(int ichOpndStart) diff --git a/src/CalcManager/CEngine/Number.cpp b/src/CalcManager/CEngine/Number.cpp index 7b3be21b..da443b12 100644 --- a/src/CalcManager/CEngine/Number.cpp +++ b/src/CalcManager/CEngine/Number.cpp @@ -22,10 +22,9 @@ namespace CalcEngine Number::Number(PNUMBER p) noexcept : m_sign{ p->sign } , m_exp{ p->exp } - , m_mantissa{} { m_mantissa.reserve(p->cdigit); - copy(p->mant, p->mant + p->cdigit, back_inserter(m_mantissa)); + copy_n(p->mant, p->cdigit, back_inserter(m_mantissa)); } PNUMBER Number::ToPNUMBER() const diff --git a/src/CalcManager/CEngine/calc.cpp b/src/CalcManager/CEngine/calc.cpp index dd70fb63..713a661c 100644 --- a/src/CalcManager/CEngine/calc.cpp +++ b/src/CalcManager/CEngine/calc.cpp @@ -101,7 +101,7 @@ CCalcEngine::CCalcEngine( { InitChopNumbers(); - m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(m_numwidth); + m_dwWordBitWidth = DwWordBitWidthFromNumWidth(m_numwidth); m_maxTrigonometricNum = RationalMath::Pow(10, 100); diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp index 72d92062..701fb21c 100644 --- a/src/CalcManager/CEngine/scicomm.cpp +++ b/src/CalcManager/CEngine/scicomm.cpp @@ -18,7 +18,6 @@ #include #include "Header Files/CalcEngine.h" #include "Header Files/CalcUtils.h" -#include "NumberFormattingUtils.h" using namespace std; using namespace CalcEngine; @@ -31,17 +30,31 @@ namespace // 0 is returned. Higher the number, higher the precedence of the operator. int NPrecedenceOfOp(int nopCode) { - static uint16_t rgbPrec[] = { 0, 0, IDC_OR, 0, IDC_XOR, 0, IDC_AND, 1, IDC_NAND, 1, IDC_NOR, 1, IDC_ADD, 2, IDC_SUB, 2, IDC_RSHF, 3, - IDC_LSHF, 3, IDC_RSHFL, 3, IDC_MOD, 3, IDC_DIV, 3, IDC_MUL, 3, IDC_PWR, 4, IDC_ROOT, 4, IDC_LOGBASEY, 4 }; - - for (unsigned int iPrec = 0; iPrec < size(rgbPrec); iPrec += 2) + switch (nopCode) { - if (nopCode == rgbPrec[iPrec]) - { - return rgbPrec[iPrec + 1]; - } + default: + case IDC_OR: + case IDC_XOR: + return 0; + case IDC_AND: + case IDC_NAND: + case IDC_NOR: + return 1; + case IDC_ADD: + case IDC_SUB: + return 2; + case IDC_LSHF: + case IDC_RSHF: + case IDC_RSHFL: + case IDC_MOD: + case IDC_DIV: + case IDC_MUL: + return 3; + case IDC_PWR: + case IDC_ROOT: + case IDC_LOGBASEY: + return 4; } - return 0; } } @@ -519,6 +532,12 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) if (wParam == IDC_OPENP) { + // if there's an omitted multiplication sign + if (IsDigitOpCode(m_nLastCom) || IsUnaryOpCode(m_nLastCom) || m_nLastCom == IDC_PNT || m_nLastCom == IDC_CLOSEP) + { + ProcessCommand(IDC_MUL); + } + CheckAndAddLastBinOpToHistory(); m_HistoryCollector.AddOpenBraceToHistory(); @@ -594,7 +613,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) // Set the "(=xx" indicator. if (nullptr != m_pCalcDisplay) { - m_pCalcDisplay->SetParenthesisNumber(m_openParenCount >= 0 ? static_cast(m_openParenCount) : 0); + m_pCalcDisplay->SetParenthesisNumber(static_cast(m_openParenCount)); } if (!m_bError) @@ -757,7 +776,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) break; case IDC_FE: // Toggle exponential notation display. - m_nFE = NumberFormat(!(int)m_nFE); + m_nFE = m_nFE == NumberFormat::Float ? NumberFormat::Scientific : NumberFormat::Float; DisplayNum(); break; diff --git a/src/CalcManager/CEngine/sciset.cpp b/src/CalcManager/CEngine/sciset.cpp index cb143559..57aeda3b 100644 --- a/src/CalcManager/CEngine/sciset.cpp +++ b/src/CalcManager/CEngine/sciset.cpp @@ -39,7 +39,7 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidt if (numwidth >= NUM_WIDTH::QWORD_WIDTH && numwidth <= NUM_WIDTH::BYTE_WIDTH) { m_numwidth = numwidth; - m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(numwidth); + m_dwWordBitWidth = DwWordBitWidthFromNumWidth(numwidth); } // inform ratpak that a change in base or precision has occurred @@ -50,7 +50,7 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidt DisplayNum(); } -int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth) +int32_t CCalcEngine::DwWordBitWidthFromNumWidth(NUM_WIDTH numwidth) { switch (numwidth) { @@ -85,7 +85,7 @@ uint32_t CCalcEngine::NRadixFromRadixType(RadixType radixtype) // Toggles a given bit into the number representation. returns true if it changed it actually. bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno) { - uint32_t wmax = DwWordBitWidthFromeNumWidth(m_numwidth); + uint32_t wmax = DwWordBitWidthFromNumWidth(m_numwidth); if (wbitno >= wmax) { return false; // ignore error cant happen diff --git a/src/CalcManager/CalcManager.vcxproj b/src/CalcManager/CalcManager.vcxproj index 80940c6a..42df6f7d 100644 --- a/src/CalcManager/CalcManager.vcxproj +++ b/src/CalcManager/CalcManager.vcxproj @@ -45,8 +45,8 @@ true Windows Store 10.0 - 10.0.18362.0 - 10.0.17134.0 + 10.0.22621.0 + 10.0.19041.0 @@ -56,28 +56,28 @@ StaticLibrary true - v142 + v143 StaticLibrary true - v142 + v143 StaticLibrary true - v142 + v143 StaticLibrary true - v142 + v143 StaticLibrary false true - v142 + v143 NativeRecommendedRules.ruleset true @@ -85,7 +85,7 @@ StaticLibrary false true - v142 + v143 NativeRecommendedRules.ruleset true @@ -93,7 +93,7 @@ StaticLibrary false true - v142 + v143 NativeRecommendedRules.ruleset true @@ -101,7 +101,7 @@ StaticLibrary false true - v142 + v143 NativeRecommendedRules.ruleset true @@ -346,4 +346,4 @@ - + \ No newline at end of file diff --git a/src/CalcManager/CalculatorHistory.cpp b/src/CalcManager/CalculatorHistory.cpp index 467cd420..c40d2299 100644 --- a/src/CalcManager/CalculatorHistory.cpp +++ b/src/CalcManager/CalculatorHistory.cpp @@ -79,7 +79,7 @@ vector> const& CalculatorHistory::GetHistory() shared_ptr const& CalculatorHistory::GetHistoryItem(unsigned int uIdx) { - assert(uIdx >= 0 && uIdx < m_historyItems.size()); + assert(uIdx < m_historyItems.size()); return m_historyItems.at(uIdx); } diff --git a/src/CalcManager/Header Files/CalcEngine.h b/src/CalcManager/Header Files/CalcEngine.h index 7709cf61..f387c020 100644 --- a/src/CalcManager/Header Files/CalcEngine.h +++ b/src/CalcManager/Header Files/CalcEngine.h @@ -179,7 +179,7 @@ private: CalcEngine::Rational SciCalcFunctions(CalcEngine::Rational const& rat, uint32_t op); CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs); void SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidth); - int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth); + int32_t DwWordBitWidthFromNumWidth(NUM_WIDTH numwidth); uint32_t NRadixFromRadixType(RadixType radixtype); double GenerateRandomNumber(); diff --git a/src/CalcManager/Header Files/History.h b/src/CalcManager/Header Files/History.h index f88f61c3..9eb0bd71 100644 --- a/src/CalcManager/Header Files/History.h +++ b/src/CalcManager/Header Files/History.h @@ -21,8 +21,8 @@ public: ~CHistoryCollector(); void AddOpndToHistory(std::wstring_view numStr, CalcEngine::Rational const& rat, bool fRepetition = false); void RemoveLastOpndFromHistory(); - void AddBinOpToHistory(int nOpCode, bool isIntgerMode, bool fNoRepetition = true); - void ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntgerMode); + void AddBinOpToHistory(int nOpCode, bool isIntegerMode, bool fNoRepetition = true); + void ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntegerMode); void AddUnaryOpToHistory(int nOpCode, bool fInv, AngleType angletype); void AddOpenBraceToHistory(); void AddCloseBraceToHistory(); diff --git a/src/CalcManager/NumberFormattingUtils.cpp b/src/CalcManager/NumberFormattingUtils.cpp index 63563972..3c5b9feb 100644 --- a/src/CalcManager/NumberFormattingUtils.cpp +++ b/src/CalcManager/NumberFormattingUtils.cpp @@ -3,7 +3,7 @@ using namespace std; -namespace CalcManager::NumberFormattingUtils +namespace UnitConversionManager::NumberFormattingUtils { /// /// Trims out any trailing zeros or decimals in the given input string diff --git a/src/CalcManager/NumberFormattingUtils.h b/src/CalcManager/NumberFormattingUtils.h index f5587fe6..05585fea 100644 --- a/src/CalcManager/NumberFormattingUtils.h +++ b/src/CalcManager/NumberFormattingUtils.h @@ -6,7 +6,7 @@ #include #include "sal_cross_platform.h" -namespace CalcManager::NumberFormattingUtils +namespace UnitConversionManager::NumberFormattingUtils { void TrimTrailingZeros(_Inout_ std::wstring& input); unsigned int GetNumberDigits(std::wstring value); diff --git a/src/CalcManager/Ratpack/CalcErr.h b/src/CalcManager/Ratpack/CalcErr.h index ebdc6730..5f7ae524 100644 --- a/src/CalcManager/Ratpack/CalcErr.h +++ b/src/CalcManager/Ratpack/CalcErr.h @@ -3,6 +3,8 @@ #pragma once +#include + // CalcErr.h // // Defines the error codes thrown by ratpak and caught by Calculator @@ -36,7 +38,7 @@ // This format is based loosely on an OLE HRESULT and is compatible with the // SUCCEEDED and FAILED macros as well as the HRESULT_CODE macro -typedef int32_t ResultCode; +using ResultCode = int32_t; // CALC_E_DIVIDEBYZERO // diff --git a/src/CalcManager/Ratpack/support.cpp b/src/CalcManager/Ratpack/support.cpp index ef9e4106..bcd31da2 100644 --- a/src/CalcManager/Ratpack/support.cpp +++ b/src/CalcManager/Ratpack/support.cpp @@ -25,7 +25,7 @@ using namespace std; -void _readconstants(void); +void _readconstants(); #if defined(GEN_CONST) static int cbitsofprecision = 0; @@ -136,13 +136,7 @@ void ChangeConstants(uint32_t radix, int32_t precision) // in the internal BASEX radix, this is important for length calculations // in translating from radix to BASEX and back. - uint64_t limit = static_cast(BASEX) / static_cast(radix); - g_ratio = 0; - for (uint32_t digit = 1; digit < limit; digit *= radix) - { - g_ratio++; - } - g_ratio += !g_ratio; + g_ratio = static_cast(ceil(BASEXPWR / log2(radix))) - 1; destroyrat(rat_nRadix); rat_nRadix = i32torat(radix); diff --git a/src/CalcManager/UnitConverter.cpp b/src/CalcManager/UnitConverter.cpp index 3d4b1865..41afd272 100644 --- a/src/CalcManager/UnitConverter.cpp +++ b/src/CalcManager/UnitConverter.cpp @@ -11,7 +11,7 @@ using namespace std; using namespace UnitConversionManager; -using namespace CalcManager::NumberFormattingUtils; +using namespace UnitConversionManager::NumberFormattingUtils; static constexpr uint32_t EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT = 3U; static constexpr uint32_t EXPECTEDSERIALIZEDUNITTOKENCOUNT = 6U; diff --git a/src/CalcManager/UnitConverter.h b/src/CalcManager/UnitConverter.h index 0ee06ae3..44255816 100644 --- a/src/CalcManager/UnitConverter.h +++ b/src/CalcManager/UnitConverter.h @@ -156,13 +156,12 @@ namespace UnitConversionManager std::wstring targetCurrencyCode; }; - typedef std::tuple, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer; - typedef std::unordered_map< + using CategorySelectionInitializer = std::tuple, UnitConversionManager::Unit, UnitConversionManager::Unit>; + using UnitToUnitToConversionDataMap = std::unordered_map< UnitConversionManager::Unit, std::unordered_map, - UnitConversionManager::UnitHash> - UnitToUnitToConversionDataMap; - typedef std::unordered_map> CategoryToUnitVectorMap; + UnitConversionManager::UnitHash>; + using CategoryToUnitVectorMap = std::unordered_map>; class IViewModelCurrencyCallback { diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index 0450741b..a5de2285 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -12,8 +12,8 @@ #include "DataLoaders/UnitConverterDataLoader.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::DataLoaders; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace CalculatorApp::ViewModel; using namespace CalculationManager; using namespace Platform; @@ -75,7 +75,7 @@ void ApplicationViewModel::Categories::set(IObservableVector void ApplicationViewModel::Initialize(ViewMode mode) { - if (!NavCategory::IsValidViewMode(mode) || !NavCategory::IsViewModeEnabled(mode)) + if (!NavCategoryStates::IsValidViewMode(mode) || !NavCategoryStates::IsViewModeEnabled(mode)) { mode = ViewMode::Standard; } @@ -124,7 +124,7 @@ bool ApplicationViewModel::TryRecoverFromNavigationModeFailure() void ApplicationViewModel::OnModeChanged() { - assert(NavCategory::IsValidViewMode(m_mode)); + assert(NavCategoryStates::IsValidViewMode(m_mode)); if (NavCategory::IsCalculatorViewMode(m_mode)) { if (!m_CalculatorViewModel) @@ -160,15 +160,15 @@ void ApplicationViewModel::OnModeChanged() } auto resProvider = AppResourceProvider::GetInstance(); - CategoryName = resProvider->GetResourceString(NavCategory::GetNameResourceKey(m_mode)); + CategoryName = resProvider->GetResourceString(NavCategoryStates::GetNameResourceKey(m_mode)); // Cast mode to an int in order to save it to app data. // Save the changed mode, so that the new window launches in this mode. // Don't save until after we have adjusted to the new mode, so we don't save a mode that fails to load. - ApplicationData::Current->LocalSettings->Values->Insert(ModePropertyName, NavCategory::Serialize(m_mode)); + ApplicationData::Current->LocalSettings->Values->Insert(ModePropertyName, NavCategoryStates::Serialize(m_mode)); // Log ModeChange event when not first launch, log WindowCreated on first launch - if (NavCategory::IsValidViewMode(m_PreviousMode)) + if (NavCategoryStates::IsValidViewMode(m_PreviousMode)) { TraceLogger::GetInstance()->LogModeChange(m_mode); } @@ -213,7 +213,7 @@ void ApplicationViewModel::SetMenuCategories() // Use the Categories property instead of the backing variable // because we want to take advantage of binding updates and // property setter logic. - Categories = NavCategoryGroup::CreateMenuOptions(); + Categories = NavCategoryStates::CreateMenuOptions(); } void ApplicationViewModel::ToggleAlwaysOnTop(float width, float height) diff --git a/src/CalcViewModel/ApplicationViewModel.h b/src/CalcViewModel/ApplicationViewModel.h index 7e4238d8..ab26c35f 100644 --- a/src/CalcViewModel/ApplicationViewModel.h +++ b/src/CalcViewModel/ApplicationViewModel.h @@ -17,14 +17,14 @@ namespace CalculatorApp public: ApplicationViewModel(); - void Initialize(CalculatorApp::Common::ViewMode mode); // Use for first init, use deserialize for rehydration + void Initialize(CalculatorApp::ViewModel::Common::ViewMode mode); // Use for first init, use deserialize for rehydration OBSERVABLE_OBJECT(); OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel); OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel ^, DateCalcViewModel); OBSERVABLE_PROPERTY_RW(GraphingCalculatorViewModel ^, GraphingCalcViewModel); OBSERVABLE_PROPERTY_RW(UnitConverterViewModel ^, ConverterViewModel); - OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode); + OBSERVABLE_PROPERTY_RW(CalculatorApp::ViewModel::Common::ViewMode, PreviousMode); OBSERVABLE_PROPERTY_R(bool, IsAlwaysOnTop); OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, CategoryName); @@ -34,14 +34,14 @@ namespace CalculatorApp COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand); COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand); - property CalculatorApp::Common::ViewMode Mode + property CalculatorApp::ViewModel::Common::ViewMode Mode { - CalculatorApp::Common::ViewMode get() + CalculatorApp::ViewModel::Common::ViewMode get() { return m_mode; } - void set(CalculatorApp::Common::ViewMode value); + void set(CalculatorApp::ViewModel::Common::ViewMode value); } static property Platform::String^ ModePropertyName { @@ -51,21 +51,21 @@ namespace CalculatorApp } } - property Windows::Foundation::Collections::IObservableVector^ Categories + property Windows::Foundation::Collections::IObservableVector^ Categories { - Windows::Foundation::Collections::IObservableVector^ get() + Windows::Foundation::Collections::IObservableVector^ get() { return m_categories; } - void set(Windows::Foundation::Collections::IObservableVector^ value); + void set(Windows::Foundation::Collections::IObservableVector^ value); } property Windows::UI::Xaml::Visibility ClearMemoryVisibility { Windows::UI::Xaml::Visibility get() { - return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible + return CalculatorApp::ViewModel::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible : Windows::UI::Xaml::Visibility::Collapsed; } } @@ -106,8 +106,8 @@ namespace CalculatorApp void SetMenuCategories(); - CalculatorApp::Common::ViewMode m_mode; - Windows::Foundation::Collections::IObservableVector ^ m_categories; + CalculatorApp::ViewModel::Common::ViewMode m_mode; + Windows::Foundation::Collections::IObservableVector ^ m_categories; Concurrency::task HandleToggleAlwaysOnTop(float width, float height); void SetDisplayNormalAlwaysOnTopOption(); }; diff --git a/src/Calculator/Calculator.rc b/src/CalcViewModel/CalcViewModel.rc similarity index 74% rename from src/Calculator/Calculator.rc rename to src/CalcViewModel/CalcViewModel.rc index 39e80483..b447542a 100644 --- a/src/Calculator/Calculator.rc +++ b/src/CalcViewModel/CalcViewModel.rc @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#define APP_FILE_NAME "Calculator" +#define APP_FILE_NAME "CalcViewModel" #define APP_FILE_IS_EXE -#define APP_PRODUCT_NAME "Microsoft Calculator" +#define APP_PRODUCT_NAME "Microsoft Calculator ViewModel" #define APP_COMPANY_NAME "Microsoft Corporation" #define APP_COPYRIGHT "\251 Microsoft Corporation. All rights reserved." diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj index c2a69b5c..b8869d4b 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj +++ b/src/CalcViewModel/CalcViewModel.vcxproj @@ -35,61 +35,61 @@ - {90e9761d-9262-4773-942d-caeae75d7140} - StaticLibrary - CalcViewModel + {812d1a7b-b8ac-49e4-8e6d-af5d59500d56} + WindowsRuntimeComponent + CalculatorApp.ViewModel en-US 14.0 true Windows Store - 10.0.18362.0 - 10.0.17134.0 + 10.0.22621.0 + 10.0.19041.0 10.0 - StaticLibrary + DynamicLibrary true - v142 + v143 - StaticLibrary + DynamicLibrary true - v142 + v143 - StaticLibrary + DynamicLibrary true - v142 + v143 - StaticLibrary + DynamicLibrary true - v142 + v143 - StaticLibrary + DynamicLibrary false true - v142 + v143 - StaticLibrary + DynamicLibrary false true - v142 + v143 - StaticLibrary + DynamicLibrary false true - v142 + v143 - StaticLibrary + DynamicLibrary false true - v142 + v143 @@ -105,13 +105,13 @@ - - - - + + + + @@ -122,175 +122,181 @@ - + + false + + + false + + + false + + + false + + + false + + + false + + + false + + false - true Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 Console false - false - - /ignore:4264 %(AdditionalOptions) - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + Guard Console false - false - - /ignore:4264 %(AdditionalOptions) - - + Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 Console false - false - - /ignore:4264 %(AdditionalOptions) - - + Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + Guard + + + Console + false + + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + + + Console + false + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + Guard Console false - false - - /ignore:4264 %(AdditionalOptions) - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 Console false - false - - /ignore:4264 %(AdditionalOptions) - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(SolutionDir);%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj /await %(AdditionalOptions) + 28204;4453 + stdcpp17 + Guard Console false - false - - /ignore:4264 %(AdditionalOptions) - - - - - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true - - - Console - false - false - - - /ignore:4264 %(AdditionalOptions) - - - - - Use - true - true - $(SolutionDir)..\src\;%(AdditionalIncludeDirectories) - 4453 - /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) - Level4 - true - - - Console - false - false - - - /ignore:4264 %(AdditionalOptions) - /DSEND_DIAGNOSTICS %(AdditionalOptions) + + 0.0.0.0 + + + + @@ -314,6 +320,7 @@ + @@ -350,6 +357,7 @@ + @@ -365,10 +373,10 @@ Create Create - Create Create - Create Create + Create + Create Create Create @@ -407,5 +415,6 @@ - + + \ No newline at end of file diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters index b219806e..46ee7fd0 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj.filters +++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters @@ -2,27 +2,20 @@ - {1daab7c4-63f6-4266-a259-f34acad66d09} + {05fb7833-4679-4430-bf21-808354e815bf} - {8d4edf06-c312-4312-978a-b6c2beb8295a} + {8f1ef587-e5ce-4fc2-b9b7-73326d5e779a} - {0184f727-b8aa-4af8-a699-63f1b56e7853} + {70216695-3d7b-451a-98e4-cacbea3ba0a6} - {cf7dca32-9727-4f98-83c3-1c0ca7dd1e0c} + {9b94309f-6b9b-4cbb-8584-4273061cc432} - - - - - - - Common @@ -56,12 +49,18 @@ Common + + Common + Common Common + + Common\Automation + Common\Automation @@ -80,26 +79,25 @@ GraphingCalculator - - Common\Automation - GraphingCalculator + + + + + + + - - - - - - - - Common + + Common + Common @@ -115,6 +113,9 @@ Common + + Common + Common @@ -145,12 +146,21 @@ Common + + Common + + + Common + Common Common + + Common\Automation + Common\Automation @@ -160,6 +170,9 @@ DataLoaders + + DataLoaders + DataLoaders @@ -169,36 +182,27 @@ DataLoaders - - DataLoaders - - - Common\Automation - - - Common - - - Common - GraphingCalculator GraphingCalculator - - Common + + GraphingCalculator GraphingCalculator - - GraphingCalculator - - - Common - + + + + + + + + + @@ -206,6 +210,6 @@ - + \ No newline at end of file diff --git a/src/CalcViewModel/Common/AppResourceProvider.cpp b/src/CalcViewModel/Common/AppResourceProvider.cpp index b843d55b..bc23e78b 100644 --- a/src/CalcViewModel/Common/AppResourceProvider.cpp +++ b/src/CalcViewModel/Common/AppResourceProvider.cpp @@ -7,6 +7,7 @@ using namespace Platform; using namespace Windows::ApplicationModel::Resources; using namespace CalculatorApp; +using namespace CalculatorApp::ViewModel::Common; AppResourceProvider::AppResourceProvider() { diff --git a/src/CalcViewModel/Common/AppResourceProvider.h b/src/CalcViewModel/Common/AppResourceProvider.h index be429a13..7af2e7fd 100644 --- a/src/CalcViewModel/Common/AppResourceProvider.h +++ b/src/CalcViewModel/Common/AppResourceProvider.h @@ -3,7 +3,7 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { public ref class AppResourceProvider sealed { diff --git a/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h b/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h index 9f947f41..7fccdaaf 100644 --- a/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h +++ b/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h @@ -9,7 +9,7 @@ // being used. Depending on the version of the OS the app is running on, // the app may need a host that uses LiveRegionChanged or RaiseNotification. -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { public interface class INarratorAnnouncementHost diff --git a/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp b/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp index 0df3a96c..e242411e 100644 --- a/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp +++ b/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "LiveRegionHost.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace Windows::UI::Xaml::Automation; using namespace Windows::UI::Xaml::Automation::Peers; using namespace Windows::UI::Xaml::Controls; diff --git a/src/CalcViewModel/Common/Automation/LiveRegionHost.h b/src/CalcViewModel/Common/Automation/LiveRegionHost.h index fef7c714..66d41e44 100644 --- a/src/CalcViewModel/Common/Automation/LiveRegionHost.h +++ b/src/CalcViewModel/Common/Automation/LiveRegionHost.h @@ -9,7 +9,7 @@ // This event is unreliable and should be deprecated in favor of the new // RaiseNotification API in RS3. -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { // This class exists so that the app can run on RS2 and use LiveRegions // to host notifications on those builds. diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp index 271a4c24..35a8a692 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp @@ -4,11 +4,11 @@ #include "pch.h" #include "NarratorAnnouncement.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace Platform; using namespace Windows::UI::Xaml::Automation::Peers; -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { namespace CalculatorActivityIds { @@ -30,6 +30,7 @@ namespace CalculatorApp::Common::Automation StringReference GraphViewBestFitChanged(L"GraphViewBestFitChanged"); StringReference AlwaysOnTop(L"AlwaysOnTop"); StringReference BitShiftRadioButtonContent(L"BitShiftRadioButtonContent"); + StringReference SettingsPageOpened(L"SettingsPageOpened"); } } @@ -204,3 +205,12 @@ NarratorAnnouncement ^ CalculatorAnnouncement::GetBitShiftRadioButtonCheckedAnno AutomationNotificationKind::ActionCompleted, AutomationNotificationProcessing::ImportantMostRecent); } + +NarratorAnnouncement ^ CalculatorAnnouncement::GetSettingsPageOpenedAnnouncement(Platform::String ^ announcement) +{ + return ref new NarratorAnnouncement( + announcement, + CalculatorActivityIds::SettingsPageOpened, + AutomationNotificationKind::ActionCompleted, + AutomationNotificationProcessing::ImportantMostRecent); +} diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h index d996a082..26196b9e 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h @@ -3,7 +3,7 @@ #pragma once -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { public ref class NarratorAnnouncement sealed @@ -28,25 +28,23 @@ public static bool IsValid(NarratorAnnouncement ^ announcement); private: - // Make CalculatorAnnouncement a friend class so it is the only - // class that can access the private constructor. - friend class CalculatorAnnouncement; + Platform::String ^ m_announcement; + Platform::String ^ m_activityId; + Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind m_kind; + Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing m_processing; + internal: NarratorAnnouncement( Platform::String ^ announcement, Platform::String ^ activityId, Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind kind, Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing processing); - - Platform::String ^ m_announcement; - Platform::String ^ m_activityId; - Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind m_kind; - Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing m_processing; }; // CalculatorAnnouncement is intended to contain only static methods // that return announcements made for the Calculator app. - class CalculatorAnnouncement +public + ref class CalculatorAnnouncement sealed { public: static NarratorAnnouncement ^ GetDisplayUpdatedAnnouncement(Platform::String ^ announcement); @@ -77,5 +75,7 @@ public static NarratorAnnouncement ^ GetAlwaysOnTopChangedAnnouncement(Platform::String ^ announcement); static NarratorAnnouncement ^ GetBitShiftRadioButtonCheckedAnnouncement(Platform::String ^ announcement); + + static NarratorAnnouncement ^ GetSettingsPageOpenedAnnouncement(Platform::String ^ announcement); }; } diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp index a103c7e7..6e8254b1 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp @@ -6,7 +6,7 @@ #include "NotificationHost.h" #include "LiveRegionHost.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace std; INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::s_hostProducer; diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h index 4b739a79..d6579617 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h @@ -9,7 +9,7 @@ // Depending on the version of the OS the app is running on, the factory will return // an announcement host appropriate for that version. -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { class NarratorAnnouncementHostFactory { diff --git a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp index 89fa0c0b..4ac4600e 100644 --- a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp @@ -6,7 +6,7 @@ #include "pch.h" #include "NarratorNotifier.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace Platform; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Automation; diff --git a/src/CalcViewModel/Common/Automation/NarratorNotifier.h b/src/CalcViewModel/Common/Automation/NarratorNotifier.h index 359bb09e..f3d82eaa 100644 --- a/src/CalcViewModel/Common/Automation/NarratorNotifier.h +++ b/src/CalcViewModel/Common/Automation/NarratorNotifier.h @@ -6,7 +6,7 @@ #pragma once #include "NarratorAnnouncement.h" -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { public ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject diff --git a/src/CalcViewModel/Common/Automation/NotificationHost.cpp b/src/CalcViewModel/Common/Automation/NotificationHost.cpp index 92bf846e..d5bc1d45 100644 --- a/src/CalcViewModel/Common/Automation/NotificationHost.cpp +++ b/src/CalcViewModel/Common/Automation/NotificationHost.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "NotificationHost.h" -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace Windows::Foundation::Metadata; using namespace Windows::UI::Xaml::Automation; using namespace Windows::UI::Xaml::Automation::Peers; diff --git a/src/CalcViewModel/Common/Automation/NotificationHost.h b/src/CalcViewModel/Common/Automation/NotificationHost.h index d0a929c6..b0e86787 100644 --- a/src/CalcViewModel/Common/Automation/NotificationHost.h +++ b/src/CalcViewModel/Common/Automation/NotificationHost.h @@ -8,7 +8,7 @@ // This class announces NarratorAnnouncements using the RaiseNotification API // available in RS3. -namespace CalculatorApp::Common::Automation +namespace CalculatorApp::ViewModel::Common::Automation { public ref class NotificationHost sealed : public INarratorAnnouncementHost @@ -23,10 +23,10 @@ public private: static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind - GetWindowsNotificationKind(CalculatorApp::Common::Automation::AutomationNotificationKind customKindType); + GetWindowsNotificationKind(CalculatorApp::ViewModel::Common::Automation::AutomationNotificationKind customKindType); static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing - GetWindowsNotificationProcessing(CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType); + GetWindowsNotificationProcessing(CalculatorApp::ViewModel::Common::Automation::AutomationNotificationProcessing customProcessingType); private: Windows::UI::Xaml::UIElement ^ m_host; diff --git a/src/CalcViewModel/Common/BitLength.h b/src/CalcViewModel/Common/BitLength.h index 8c38e7e4..065bd25e 100644 --- a/src/CalcViewModel/Common/BitLength.h +++ b/src/CalcViewModel/Common/BitLength.h @@ -1,6 +1,6 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { diff --git a/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.cpp b/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.cpp index 76c0d4c0..899af3ec 100644 --- a/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.cpp +++ b/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.cpp @@ -5,7 +5,8 @@ #include "CalculatorButtonPressedEventArgs.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel; +using namespace CalculatorApp::ViewModel::Common; using namespace Platform; NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(_In_ Object ^ commandParameter) diff --git a/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.h b/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.h index 27624987..58192d41 100644 --- a/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.h +++ b/src/CalcViewModel/Common/CalculatorButtonPressedEventArgs.h @@ -6,7 +6,7 @@ #include "CalculatorButtonUser.h" #include "Utils.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { @@ -15,15 +15,15 @@ namespace CalculatorApp { public: PROPERTY_R(Platform::String ^, AuditoryFeedback); - PROPERTY_R(CalculatorApp::NumbersAndOperatorsEnum, Operation); + PROPERTY_R(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum, Operation); - CalculatorButtonPressedEventArgs(Platform::String ^ feedback, CalculatorApp::NumbersAndOperatorsEnum operation) + CalculatorButtonPressedEventArgs(Platform::String ^ feedback, CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum operation) : m_AuditoryFeedback(feedback) , m_Operation(operation) { } - static CalculatorApp::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object ^ commandParameter); + static CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object ^ commandParameter); static Platform::String ^ GetAuditoryFeedbackFromCommandParameter(_In_ Platform::Object ^ commandParameter); }; } diff --git a/src/CalcViewModel/Common/CalculatorButtonUser.h b/src/CalcViewModel/Common/CalculatorButtonUser.h index 0d09de6e..4885e488 100644 --- a/src/CalcViewModel/Common/CalculatorButtonUser.h +++ b/src/CalcViewModel/Common/CalculatorButtonUser.h @@ -5,12 +5,11 @@ #include "CalcManager/Command.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { namespace CM = CalculationManager; -public - enum class NumbersAndOperatorsEnum + public enum class NumbersAndOperatorsEnum { Zero = (int)CM::Command::Command0, One = (int)CM::Command::Command1, diff --git a/src/CalcViewModel/Common/CalculatorDisplay.cpp b/src/CalcViewModel/Common/CalculatorDisplay.cpp index 5cf8afbc..afd42a0c 100644 --- a/src/CalcViewModel/Common/CalculatorDisplay.cpp +++ b/src/CalcViewModel/Common/CalculatorDisplay.cpp @@ -8,143 +8,149 @@ #include "StandardCalculatorViewModel.h" using namespace CalculatorApp; +using namespace CalculatorApp::ViewModel; +using namespace CalculatorApp::ViewModel::Common; using namespace CalculationManager; using namespace Platform; using namespace std; -CalculatorDisplay::CalculatorDisplay() +namespace CalculatorApp::ViewModel::Common { -} - -void CalculatorDisplay::SetCallback(Platform::WeakReference callbackReference) -{ - m_callbackReference = callbackReference; -} - -void CalculatorDisplay::SetHistoryCallback(Platform::WeakReference callbackReference) -{ - m_historyCallbackReference = callbackReference; -} - -void CalculatorDisplay::SetPrimaryDisplay(_In_ const wstring& displayStringValue, _In_ bool isError) -{ - if (m_callbackReference) + CalculatorDisplay::CalculatorDisplay() { - if (auto calcVM = m_callbackReference.Resolve()) + } + + void CalculatorDisplay::SetCallback(Platform::WeakReference callbackReference) + { + m_callbackReference = callbackReference; + } + + void CalculatorDisplay::SetHistoryCallback(Platform::WeakReference callbackReference) + { + m_historyCallbackReference = callbackReference; + } + + void CalculatorDisplay::SetPrimaryDisplay(_In_ const wstring& displayStringValue, _In_ bool isError) + { + if (m_callbackReference) { - calcVM->SetPrimaryDisplay(StringReference(displayStringValue.c_str()), isError); + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->SetPrimaryDisplay(StringReference(displayStringValue.c_str()), isError); + } + } + } + + void CalculatorDisplay::SetParenthesisNumber(_In_ unsigned int parenthesisCount) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->SetParenthesisCount(parenthesisCount); + } + } + } + + void CalculatorDisplay::OnNoRightParenAdded() + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnNoRightParenAdded(); + } + } + } + + void CalculatorDisplay::SetIsInError(bool isError) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->IsInError = isError; + } + } + } + + void CalculatorDisplay::SetExpressionDisplay( + _Inout_ std::shared_ptr>> const& tokens, + _Inout_ std::shared_ptr>> const& commands) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->SetExpressionDisplay(tokens, commands); + } + } + } + + void CalculatorDisplay::SetMemorizedNumbers(_In_ const vector& newMemorizedNumbers) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->SetMemorizedNumbers(newMemorizedNumbers); + } + } + } + + void CalculatorDisplay::OnHistoryItemAdded(_In_ unsigned int addedItemIndex) + { + if (m_historyCallbackReference != nullptr) + { + if (auto historyVM = m_historyCallbackReference.Resolve()) + { + historyVM->OnHistoryItemAdded(addedItemIndex); + } + } + } + + void CalculatorDisplay::MaxDigitsReached() + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnMaxDigitsReached(); + } + } + } + + void CalculatorDisplay::BinaryOperatorReceived() + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnBinaryOperatorReceived(); + } + } + } + + void CalculatorDisplay::MemoryItemChanged(unsigned int indexOfMemory) + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnMemoryItemChanged(indexOfMemory); + } + } + } + + void CalculatorDisplay::InputChanged() + { + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnInputChanged(); + } } } } -void CalculatorDisplay::SetParenthesisNumber(_In_ unsigned int parenthesisCount) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->SetParenthesisCount(parenthesisCount); - } - } -} - -void CalculatorDisplay::OnNoRightParenAdded() -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnNoRightParenAdded(); - } - } -} - -void CalculatorDisplay::SetIsInError(bool isError) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->IsInError = isError; - } - } -} - -void CalculatorDisplay::SetExpressionDisplay( - _Inout_ std::shared_ptr>> const& tokens, - _Inout_ std::shared_ptr>> const& commands) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->SetExpressionDisplay(tokens, commands); - } - } -} - -void CalculatorDisplay::SetMemorizedNumbers(_In_ const vector& newMemorizedNumbers) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->SetMemorizedNumbers(newMemorizedNumbers); - } - } -} - -void CalculatorDisplay::OnHistoryItemAdded(_In_ unsigned int addedItemIndex) -{ - if (m_historyCallbackReference != nullptr) - { - if (auto historyVM = m_historyCallbackReference.Resolve()) - { - historyVM->OnHistoryItemAdded(addedItemIndex); - } - } -} - -void CalculatorDisplay::MaxDigitsReached() -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnMaxDigitsReached(); - } - } -} - -void CalculatorDisplay::BinaryOperatorReceived() -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnBinaryOperatorReceived(); - } - } -} - -void CalculatorDisplay::MemoryItemChanged(unsigned int indexOfMemory) -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnMemoryItemChanged(indexOfMemory); - } - } -} - -void CalculatorDisplay::InputChanged() -{ - if (m_callbackReference != nullptr) - { - if (auto calcVM = m_callbackReference.Resolve()) - { - calcVM->OnInputChanged(); - } - } -} diff --git a/src/CalcViewModel/Common/CalculatorDisplay.h b/src/CalcViewModel/Common/CalculatorDisplay.h index 921260da..f6c45ae0 100644 --- a/src/CalcViewModel/Common/CalculatorDisplay.h +++ b/src/CalcViewModel/Common/CalculatorDisplay.h @@ -5,7 +5,7 @@ #include "CalcManager/Header Files/ICalcDisplay.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { // Callback interface to be implemented by the CalculatorManager class CalculatorDisplay : public ICalcDisplay diff --git a/src/CalcViewModel/Common/CopyPasteManager.cpp b/src/CalcViewModel/Common/CopyPasteManager.cpp index 8f84eead..d7f85dde 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.cpp +++ b/src/CalcViewModel/Common/CopyPasteManager.cpp @@ -9,7 +9,8 @@ using namespace std; using namespace concurrency; using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace Platform::Collections; using namespace Windows::Foundation; @@ -96,7 +97,7 @@ bool CopyPasteManager::HasStringToPaste() String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, NumberBase programmerNumberBase, BitLength bitLengthType) { - return ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType); + return ValidatePasteExpression(pastedText, mode, NavCategoryStates::GetGroupType(mode), programmerNumberBase, bitLengthType); } // return "NoOp" if pastedText is invalid else return pastedText @@ -116,7 +117,7 @@ String } // Get english translated expression - String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pastedText); + String ^ englishString = LocalizationSettings::GetInstance()->GetEnglishValueFromLocalizedDigits(pastedText); // Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333 auto pasteExpression = wstring(RemoveUnwantedCharsFromString(englishString)->Data()); @@ -287,9 +288,8 @@ bool CopyPasteManager::ExpressionRegExMatch( } else if (mode == ViewMode::Programmer) { - patterns.assign( - programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].begin(), - programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].end()); + auto pattern = &programmerModePatterns[static_cast(programmerNumberBase) - static_cast(NumberBase::HexBase)]; + patterns.assign(pattern->begin(), pattern->end()); } else if (modeType == CategoryGroupType::Converter) { @@ -504,18 +504,15 @@ ULONG32 CopyPasteManager::StandardScientificOperandLength(Platform::String ^ ope const bool hasDecimal = operandWstring.find('.') != wstring::npos; auto length = operandWstring.length(); - if (hasDecimal) + if (hasDecimal && length >= 2) { - if (length >= 2) + if ((operandWstring[0] == L'0') && (operandWstring[1] == L'.')) { - if ((operandWstring[0] == L'0') && (operandWstring[1] == L'.')) - { - length -= 2; - } - else - { - length -= 1; - } + length -= 2; + } + else + { + length -= 1; } } @@ -614,7 +611,7 @@ ULONG32 CopyPasteManager::ProgrammerOperandLength(Platform::String ^ operand, Nu Platform::String ^ CopyPasteManager::RemoveUnwantedCharsFromString(Platform::String ^ input) { constexpr wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237, 160 }; - input = CalculatorApp::Common::LocalizationSettings::GetInstance().RemoveGroupSeparators(input); + input = CalculatorApp::ViewModel::Common::LocalizationSettings::GetInstance()->RemoveGroupSeparators(input); return ref new String(Utils::RemoveUnwantedCharsFromString(input->Data(), unWantedChars).c_str()); } diff --git a/src/CalcViewModel/Common/CopyPasteManager.h b/src/CalcViewModel/Common/CopyPasteManager.h index ae59a4db..1153d81b 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.h +++ b/src/CalcViewModel/Common/CopyPasteManager.h @@ -13,10 +13,9 @@ namespace CalculatorUnitTests class CopyPasteManagerTest; } -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { -public - value struct CopyPasteMaxOperandLengthAndValue + public value struct CopyPasteMaxOperandLengthAndValue { unsigned int maxLength; unsigned long long maxValue; @@ -26,9 +25,11 @@ public { public: static void CopyToClipboard(Platform::String ^ stringToCopy); - static Windows::Foundation::IAsyncOperation< - Platform::String - ^> ^ GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, CalculatorApp::Common::NumberBase programmerNumberBase, CalculatorApp::Common::BitLength bitLengthType); + static Windows::Foundation::IAsyncOperation ^ GetStringToPaste( + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static bool HasStringToPaste(); static bool IsErrorMessage(Platform::String ^ message); static property unsigned int MaxPasteableLength @@ -87,39 +88,39 @@ public static Platform::String ^ ValidatePasteExpression( Platform::String ^ pastedText, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::NumberBase programmerNumberBase, - CalculatorApp::Common::BitLength bitLengthType); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static Platform::String ^ ValidatePasteExpression( Platform::String ^ pastedText, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - CalculatorApp::Common::NumberBase programmerNumberBase, - CalculatorApp::Common::BitLength bitLengthType); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static CopyPasteMaxOperandLengthAndValue GetMaxOperandLengthAndValue( - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - CalculatorApp::Common::NumberBase programmerNumberBase, - CalculatorApp::Common::BitLength bitLengthType); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static Windows::Foundation::Collections::IVector< - Platform::String ^> ^ ExtractOperands(Platform::String ^ pasteExpression, CalculatorApp::Common::ViewMode mode); + Platform::String ^> ^ ExtractOperands(Platform::String ^ pasteExpression, CalculatorApp::ViewModel::Common::ViewMode mode); static bool ExpressionRegExMatch( Windows::Foundation::Collections::IVector ^ operands, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - CalculatorApp::Common::NumberBase programmerNumberBase, - CalculatorApp::Common::BitLength bitLengthType); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase, + CalculatorApp::ViewModel::Common::BitLength bitLengthType); static Platform::String ^ SanitizeOperand(Platform::String ^ operand); static Platform::String ^ RemoveUnwantedCharsFromString(Platform::String ^ input); - static Platform::IBox ^ TryOperandToULL(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase); + static Platform::IBox ^ TryOperandToULL(Platform::String ^ operand, CalculatorApp::ViewModel::Common::NumberBase numberBase); static ULONG32 StandardScientificOperandLength(Platform::String ^ operand); static ULONG32 OperandLength( Platform::String ^ operand, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - CalculatorApp::Common::NumberBase programmerNumberBase); - static ULONG32 ProgrammerOperandLength(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase); + CalculatorApp::ViewModel::Common::ViewMode mode, + CalculatorApp::ViewModel::Common::CategoryGroupType modeType, + CalculatorApp::ViewModel::Common::NumberBase programmerNumberBase); + static ULONG32 ProgrammerOperandLength(Platform::String ^ operand, CalculatorApp::ViewModel::Common::NumberBase numberBase); private: static constexpr size_t MaxStandardOperandLengthValue = 16; diff --git a/src/CalcViewModel/Common/DateCalculator.cpp b/src/CalcViewModel/Common/DateCalculator.cpp index 35df7231..0b417387 100644 --- a/src/CalcViewModel/Common/DateCalculator.cpp +++ b/src/CalcViewModel/Common/DateCalculator.cpp @@ -7,7 +7,7 @@ using namespace Platform; using namespace Windows::Foundation; using namespace Windows::Globalization; -using namespace CalculatorApp::Common::DateCalculation; +using namespace CalculatorApp::ViewModel::Common::DateCalculation; bool operator==(const DateDifference& l, const DateDifference& r) { diff --git a/src/CalcViewModel/Common/DateCalculator.h b/src/CalcViewModel/Common/DateCalculator.h index 7c9b6c4d..89275b1f 100644 --- a/src/CalcViewModel/Common/DateCalculator.h +++ b/src/CalcViewModel/Common/DateCalculator.h @@ -13,7 +13,7 @@ const int c_unitsOfDate = 4; // Units Year,Month,Week,Day const int c_unitsGreaterThanDays = 3; // Units Greater than Days (Year/Month/Week) 3 const int c_daysInWeek = 7; -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { @@ -68,4 +68,4 @@ namespace CalculatorApp } } -bool operator==(const CalculatorApp::Common::DateCalculation::DateDifference& l, const CalculatorApp::Common::DateCalculation::DateDifference& r); +bool operator==(const CalculatorApp::ViewModel::Common::DateCalculation::DateDifference& l, const CalculatorApp::ViewModel::Common::DateCalculation::DateDifference& r); diff --git a/src/CalcViewModel/Common/DelegateCommand.h b/src/CalcViewModel/Common/DelegateCommand.h index 3a341287..6a0151a1 100644 --- a/src/CalcViewModel/Common/DelegateCommand.h +++ b/src/CalcViewModel/Common/DelegateCommand.h @@ -3,22 +3,18 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { - template - ref class DelegateCommand : public Windows::UI::Xaml::Input::ICommand + public delegate void DelegateCommandHandler(Platform::Object ^ parameter); + + public ref class DelegateCommand sealed : public Windows::UI::Xaml::Input::ICommand { - internal : - - typedef void (TTarget::*CommandHandlerFunc)(Platform::Object ^); - - DelegateCommand(TTarget ^ target, CommandHandlerFunc func) - : m_weakTarget(target) - , m_function(func) - { - } + public: + DelegateCommand(DelegateCommandHandler ^ handler) + : m_handler(handler) + {} private: // Explicit, and private, implementation of ICommand, this way of programming makes it so @@ -27,11 +23,7 @@ namespace CalculatorApp // code in the app calling Execute. virtual void ExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute { - TTarget ^ target = m_weakTarget.Resolve(); - if (target) - { - (target->*m_function)(parameter); - } + m_handler->Invoke(parameter); } virtual bool CanExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute @@ -39,9 +31,9 @@ namespace CalculatorApp return true; } - virtual event Windows::Foundation::EventHandler^ CanExecuteChangedImpl + virtual event Windows::Foundation::EventHandler ^ CanExecuteChangedImpl { - virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::EventHandler^ handler) sealed = Windows::UI::Xaml::Input::ICommand::CanExecuteChanged::add + virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::EventHandler ^ handler) sealed = Windows::UI::Xaml::Input::ICommand::CanExecuteChanged::add { return m_canExecuteChanged += handler; } @@ -52,17 +44,25 @@ namespace CalculatorApp } private: + DelegateCommandHandler ^ m_handler; - event Windows::Foundation::EventHandler^ m_canExecuteChanged; - - CommandHandlerFunc m_function; - Platform::WeakReference m_weakTarget; + event Windows::Foundation::EventHandler ^ m_canExecuteChanged; }; template - DelegateCommand ^ MakeDelegate(TTarget ^ target, TFuncPtr&& function) { - return ref new DelegateCommand(target, std::forward(function)); - } - + DelegateCommandHandler ^ MakeDelegateCommandHandler(TTarget ^ target, TFuncPtr&& function) + { + Platform::WeakReference weakTarget(target); + return ref new DelegateCommandHandler([weakTarget, function=std::forward(function)](Platform::Object ^ param) + { + TTarget ^ thatTarget = weakTarget.Resolve(); + if (nullptr != thatTarget) + { + (thatTarget->*function)(param); + } + } + ); + } } } + diff --git a/src/CalcViewModel/Common/DisplayExpressionToken.h b/src/CalcViewModel/Common/DisplayExpressionToken.h index aaaaf37c..c53c4857 100644 --- a/src/CalcViewModel/Common/DisplayExpressionToken.h +++ b/src/CalcViewModel/Common/DisplayExpressionToken.h @@ -5,7 +5,7 @@ #include "Utils.h" -namespace CalculatorApp::Common +namespace CalculatorApp::ViewModel::Common { public enum class TokenType @@ -33,6 +33,7 @@ public OBSERVABLE_PROPERTY_RW(int, TokenPosition); OBSERVABLE_PROPERTY_RW(bool, IsTokenEditable); OBSERVABLE_PROPERTY_RW(int, CommandIndex); + OBSERVABLE_PROPERTY_RW(TokenType, Type); OBSERVABLE_PROPERTY_R(Platform::String ^, OriginalToken); property bool IsTokenInEditMode @@ -50,7 +51,6 @@ public m_InEditMode = val; } } - internal : OBSERVABLE_PROPERTY_RW(TokenType, Type); private: bool m_InEditMode; diff --git a/src/CalcViewModel/Common/EngineResourceProvider.cpp b/src/CalcViewModel/Common/EngineResourceProvider.cpp index 05faff9f..ff274d1d 100644 --- a/src/CalcViewModel/Common/EngineResourceProvider.cpp +++ b/src/CalcViewModel/Common/EngineResourceProvider.cpp @@ -5,7 +5,7 @@ #include "EngineResourceProvider.h" #include "Common/LocalizationSettings.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace Platform; using namespace Windows::ApplicationModel::Resources; using namespace std; @@ -19,16 +19,16 @@ namespace CalculatorApp wstring EngineResourceProvider::GetCEngineString(wstring_view id) { - const auto& localizationSettings = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizationSettings = LocalizationSettings::GetInstance(); if (id.compare(L"sDecimal") == 0) { - return localizationSettings.GetDecimalSeparatorStr(); + return localizationSettings->GetDecimalSeparatorStr(); } if (id.compare(L"sThousand") == 0) { - return localizationSettings.GetNumberGroupingSeparatorStr(); + return localizationSettings->GetNumberGroupingSeparatorStr(); } if (id.compare(L"sGrouping") == 0) @@ -39,7 +39,7 @@ namespace CalculatorApp // 3;2;0 0x023 - group 1st 3 and then every 2 digits // 4;0 0x004 - group every 4 digits // 5;3;2;0 0x235 - group 5, then 3, then every 2 - wstring numberGroupingString = localizationSettings.GetNumberGroupingStr(); + wstring numberGroupingString = localizationSettings->GetNumberGroupingStr(); return numberGroupingString; } diff --git a/src/CalcViewModel/Common/EngineResourceProvider.h b/src/CalcViewModel/Common/EngineResourceProvider.h index f4620c5c..524b7a9b 100644 --- a/src/CalcViewModel/Common/EngineResourceProvider.h +++ b/src/CalcViewModel/Common/EngineResourceProvider.h @@ -5,7 +5,7 @@ #include "CalcManager/CalculatorResource.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { class EngineResourceProvider : public CalculationManager::IResourceProvider { diff --git a/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp b/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp index 509a1659..1e9859cf 100644 --- a/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp +++ b/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "ExpressionCommandDeserializer.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace Windows::Storage::Streams; CommandDeserializer::CommandDeserializer(_In_ DataReader ^ dataReader) @@ -17,24 +17,16 @@ std::shared_ptr CommandDeserializer::Deserialize(_In_ Calcul switch (cmdType) { case CalculationManager::CommandType::OperandCommand: - return std::make_shared(DeserializeOperand()); - break; case CalculationManager::CommandType::Parentheses: - return std::make_shared(DeserializeParentheses()); - break; case CalculationManager::CommandType::UnaryCommand: - return std::make_shared(DeserializeUnary()); - break; case CalculationManager::CommandType::BinaryCommand: - return std::make_shared(DeserializeBinary()); - break; default: throw ref new Platform::Exception(E_INVALIDARG, ref new Platform::String(L"Unknown command type")); diff --git a/src/CalcViewModel/Common/ExpressionCommandDeserializer.h b/src/CalcViewModel/Common/ExpressionCommandDeserializer.h index 833b6bf6..aed9afe2 100644 --- a/src/CalcViewModel/Common/ExpressionCommandDeserializer.h +++ b/src/CalcViewModel/Common/ExpressionCommandDeserializer.h @@ -5,7 +5,7 @@ #include "CalcManager/ExpressionCommand.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { diff --git a/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp b/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp index fb0cd83a..464bc023 100644 --- a/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp +++ b/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "Common/ExpressionCommandSerializer.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace Windows::Storage::Streams; SerializeCommandVisitor::SerializeCommandVisitor(_In_ DataWriter ^ dataWriter) diff --git a/src/CalcViewModel/Common/ExpressionCommandSerializer.h b/src/CalcViewModel/Common/ExpressionCommandSerializer.h index 23303fe7..d64b19b7 100644 --- a/src/CalcViewModel/Common/ExpressionCommandSerializer.h +++ b/src/CalcViewModel/Common/ExpressionCommandSerializer.h @@ -5,7 +5,7 @@ #include "CalcManager/ExpressionCommand.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { diff --git a/src/CalcViewModel/Common/LocalizationService.cpp b/src/CalcViewModel/Common/LocalizationService.cpp index 0e1cb317..5c28e42d 100644 --- a/src/CalcViewModel/Common/LocalizationService.cpp +++ b/src/CalcViewModel/Common/LocalizationService.cpp @@ -6,8 +6,9 @@ #include "LocalizationSettings.h" #include "AppResourceProvider.h" -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::LocalizationServiceProperties; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::LocalizationServiceProperties; +using namespace CalculatorApp::ViewModel; using namespace Concurrency; using namespace Platform; using namespace Platform::Collections; @@ -371,7 +372,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject ^ target) // If successful, returns a formatter that respects the user's regional format settings, // as configured by running intl.cpl. -DecimalFormatter ^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter() const +DecimalFormatter ^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter() { IIterable ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); if (languageIdentifiers != nullptr) @@ -386,7 +387,7 @@ DecimalFormatter ^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter // as configured by running intl.cpl. // // This helper function creates a DateTimeFormatter with a TwentyFour hour clock -DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format) const +DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format) { IIterable ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); if (languageIdentifiers == nullptr) @@ -399,7 +400,7 @@ DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatt // If successful, returns a formatter that respects the user's regional format settings, // as configured by running intl.cpl. -DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format, _In_ String ^ calendarIdentifier, _In_ String ^ clockIdentifier) const +DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format, _In_ String ^ calendarIdentifier, _In_ String ^ clockIdentifier) { IIterable ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); if (languageIdentifiers == nullptr) @@ -410,7 +411,7 @@ DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatt return ref new DateTimeFormatter(format, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion, calendarIdentifier, clockIdentifier); } -CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter() const +CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter() { String ^ userCurrency = (GlobalizationPreferences::Currencies->Size > 0) ? GlobalizationPreferences::Currencies->GetAt(0) : StringReference(DefaultCurrencyCode.data()); @@ -423,7 +424,7 @@ CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatt auto currencyFormatter = ref new CurrencyFormatter(userCurrency, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion); - int fractionDigits = LocalizationSettings::GetInstance().GetCurrencyTrailingDigits(); + int fractionDigits = LocalizationSettings::GetInstance()->GetCurrencyTrailingDigits(); currencyFormatter->FractionDigits = fractionDigits; return currencyFormatter; diff --git a/src/CalcViewModel/Common/LocalizationService.h b/src/CalcViewModel/Common/LocalizationService.h index d6921371..ae7a513e 100644 --- a/src/CalcViewModel/Common/LocalizationService.h +++ b/src/CalcViewModel/Common/LocalizationService.h @@ -5,7 +5,7 @@ #include "Utils.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { @@ -30,10 +30,7 @@ namespace CalculatorApp DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(LanguageFontType, FontType, LanguageFontType::UIText); DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(double, FontSize); - internal: static LocalizationService ^ GetInstance(); - static void OverrideWithLanguage(_In_ const wchar_t* const language); - Windows::UI::Xaml::FlowDirection GetFlowDirection(); bool IsRtlLayout(); bool GetOverrideFontApiValues(); @@ -42,7 +39,17 @@ namespace CalculatorApp Platform::String ^ GetFontFamilyOverride(); Windows::UI::Text::FontWeight GetFontWeightOverride(); double GetFontScaleFactorOverride(LanguageFontType fontType); + Windows::Globalization::NumberFormatting::DecimalFormatter ^ GetRegionalSettingsAwareDecimalFormatter(); + Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format); + Windows::Globalization::DateTimeFormatting::DateTimeFormatter + ^ GetRegionalSettingsAwareDateTimeFormatter( + _In_ Platform::String ^ format, + _In_ Platform::String ^ calendarIdentifier, + _In_ Platform::String ^ clockIdentifier); + Windows::Globalization::NumberFormatting::CurrencyFormatter ^ GetRegionalSettingsAwareCurrencyFormatter(); + internal: + static void OverrideWithLanguage(_In_ const wchar_t* const language); void Sort(std::vector& source); template @@ -56,16 +63,6 @@ namespace CalculatorApp }); } - Windows::Globalization::NumberFormatting::DecimalFormatter ^ GetRegionalSettingsAwareDecimalFormatter() const; - Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format) const; - Windows::Globalization::DateTimeFormatting::DateTimeFormatter - ^ GetRegionalSettingsAwareDateTimeFormatter( - _In_ Platform::String ^ format, - _In_ Platform::String ^ calendarIdentifier, - _In_ Platform::String ^ clockIdentifier) const; - - Windows::Globalization::NumberFormatting::CurrencyFormatter ^ GetRegionalSettingsAwareCurrencyFormatter() const; - static Platform::String ^ GetNarratorReadableToken(Platform::String ^ rawToken); static Platform::String ^ GetNarratorReadableString(Platform::String ^ rawString); @@ -101,6 +98,5 @@ namespace CalculatorApp double m_uiCaptionFontScaleFactorOverride; std::locale m_locale; }; - } } diff --git a/src/CalcViewModel/Common/LocalizationSettings.h b/src/CalcViewModel/Common/LocalizationSettings.h index 799e6438..0c1db651 100644 --- a/src/CalcViewModel/Common/LocalizationSettings.h +++ b/src/CalcViewModel/Common/LocalizationSettings.h @@ -6,22 +6,191 @@ #include -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { - class LocalizationSettings + public ref class LocalizationSettings sealed { private: LocalizationSettings() // Use DecimalFormatter as it respects the locale and the user setting - : LocalizationSettings(LocalizationService::GetInstance()->GetRegionalSettingsAwareDecimalFormatter()) { + Initialize(LocalizationService::GetInstance()->GetRegionalSettingsAwareDecimalFormatter()); } public: // This is only public for unit testing purposes. LocalizationSettings(Windows::Globalization::NumberFormatting::DecimalFormatter ^ formatter) + { + Initialize(formatter); + } + + // Provider of the singleton LocalizationSettings instance. + static LocalizationSettings^ GetInstance() + { + static LocalizationSettings^ localizationSettings = ref new LocalizationSettings(); + return localizationSettings; + } + + Platform::String ^ GetLocaleName() + { + return m_resolvedName; + } + + bool IsDigitEnUsSetting() + { + return (this->GetDigitSymbolFromEnUsDigit('0') == L'0'); + } + + Platform::String ^ GetEnglishValueFromLocalizedDigits(Platform::String ^ localizedString) + { + if (m_resolvedName == L"en-US") + { + return localizedString; + } + + std::wstring englishString; + englishString.reserve(localizedString->Length()); + + for (wchar_t ch : localizedString) + { + if (!IsEnUsDigit(ch)) + { + auto it = std::find(m_digitSymbols.begin(), m_digitSymbols.end(), ch); + + if (it != m_digitSymbols.end()) + { + auto index = std::distance(m_digitSymbols.begin(), it); + ch = index.ToString()->Data()[0]; + } + } + if (ch == m_decimalSeparator) + { + ch = L'.'; + } + englishString += ch; + } + + return ref new Platform::String(englishString.c_str()); + } + + Platform::String ^ RemoveGroupSeparators(Platform::String ^ source) + { + std::wstring destination; + std::copy_if( + begin(source), end(source), std::back_inserter(destination), [this](auto const c) { return c != L' ' && c != m_numberGroupSeparator; }); + + return ref new Platform::String(destination.c_str()); + } + + Platform::String ^ GetCalendarIdentifier() + { + return m_calendarIdentifier; + } + + Windows::Globalization::DayOfWeek GetFirstDayOfWeek() + { + return m_firstDayOfWeek; + } + + int GetCurrencyTrailingDigits() + { + return m_currencyTrailingDigits; + } + + int GetCurrencySymbolPrecedence() + { + return m_currencySymbolPrecedence; + } + + wchar_t GetDecimalSeparator() + { + return m_decimalSeparator; + } + + wchar_t GetDigitSymbolFromEnUsDigit(wchar_t digitSymbol) + { + assert(digitSymbol >= L'0' && digitSymbol <= L'9'); + int digit = digitSymbol - L'0'; + return m_digitSymbols.at(digit); // throws on out of range + } + + wchar_t GetNumberGroupSeparator() + { + return m_numberGroupSeparator; + } + + bool IsEnUsDigit(wchar_t digit) + { + return (digit >= L'0' && digit <= L'9'); + } + + bool IsLocalizedDigit(wchar_t digit) + { + return std::find(m_digitSymbols.begin(), m_digitSymbols.end(), digit) != m_digitSymbols.end(); + } + + bool IsLocalizedHexDigit(wchar_t digit) + { + if (IsLocalizedDigit(digit)) + { + return true; + } + + return std::find(s_hexSymbols.begin(), s_hexSymbols.end(), digit) != s_hexSymbols.end(); + } + + Platform::String ^ GetListSeparatorWinRT() + { + return ref new Platform::String(GetListSeparator().c_str()); + } + + Platform::String ^ GetDecimalSeparatorStrWinRT() + { + return ref new Platform::String(GetDecimalSeparatorStr().c_str()); + } + + internal: + void LocalizeDisplayValue(_Inout_ std::wstring* stringToLocalize) + { + if (IsDigitEnUsSetting()) + { + return; + } + + for (wchar_t& ch : *stringToLocalize) + { + if (IsEnUsDigit(ch)) + { + ch = GetDigitSymbolFromEnUsDigit(ch); + } + } + } + + std::wstring GetDecimalSeparatorStr() + { + return std::wstring(1, m_decimalSeparator); + } + + std::wstring GetNumberGroupingSeparatorStr() + { + return std::wstring(1, m_numberGroupSeparator); + } + + std::wstring GetNumberGroupingStr() + { + return m_numberGrouping; + } + + std::wstring GetListSeparator() + { + return m_listSeparator; + } + + + private: + void Initialize(Windows::Globalization::NumberFormatting::DecimalFormatter ^ formatter) { formatter->FractionDigits = 0; formatter->IsDecimalPointAlwaysDisplayed = false; @@ -125,167 +294,6 @@ namespace CalculatorApp m_firstDayOfWeek = static_cast((_wtoi(day) + 1) % 7); // static cast int to DayOfWeek enum } - // A LocalizationSettings object is not copyable. - LocalizationSettings(const LocalizationSettings&) = delete; - LocalizationSettings& operator=(const LocalizationSettings&) = delete; - - // A LocalizationSettings object is not moveable. - LocalizationSettings(LocalizationSettings&&) = delete; - LocalizationSettings& operator=(LocalizationSettings&&) = delete; - - // Provider of the singleton LocalizationSettings instance. - static const LocalizationSettings& GetInstance() - { - static const LocalizationSettings localizationSettings; - - return localizationSettings; - } - - Platform::String ^ GetLocaleName() const - { - return m_resolvedName; - } - - bool IsDigitEnUsSetting() const - { - return (this->GetDigitSymbolFromEnUsDigit('0') == L'0'); - } - - void LocalizeDisplayValue(_Inout_ std::wstring* stringToLocalize) const - { - if (IsDigitEnUsSetting()) - { - return; - } - - for (wchar_t& ch : *stringToLocalize) - { - if (IsEnUsDigit(ch)) - { - ch = GetDigitSymbolFromEnUsDigit(ch); - } - } - } - - Platform::String ^ GetEnglishValueFromLocalizedDigits(Platform::String ^ localizedString) const - { - if (m_resolvedName == L"en-US") - { - return localizedString; - } - - std::wstring englishString; - englishString.reserve(localizedString->Length()); - - for (wchar_t ch : localizedString) - { - if (!IsEnUsDigit(ch)) - { - auto it = std::find(m_digitSymbols.begin(), m_digitSymbols.end(), ch); - - if (it != m_digitSymbols.end()) - { - auto index = std::distance(m_digitSymbols.begin(), it); - ch = index.ToString()->Data()[0]; - } - } - if (ch == m_decimalSeparator) - { - ch = L'.'; - } - englishString += ch; - } - - return ref new Platform::String(englishString.c_str()); - } - - bool IsEnUsDigit(const wchar_t digit) const - { - return (digit >= L'0' && digit <= L'9'); - } - - bool IsLocalizedDigit(const wchar_t digit) const - { - return std::find(m_digitSymbols.begin(), m_digitSymbols.end(), digit) != m_digitSymbols.end(); - } - - bool IsLocalizedHexDigit(const wchar_t digit) const - { - if (IsLocalizedDigit(digit)) - { - return true; - } - - return std::find(s_hexSymbols.begin(), s_hexSymbols.end(), digit) != s_hexSymbols.end(); - } - - wchar_t GetDigitSymbolFromEnUsDigit(wchar_t digitSymbol) const - { - assert(digitSymbol >= L'0' && digitSymbol <= L'9'); - int digit = digitSymbol - L'0'; - return m_digitSymbols.at(digit); // throws on out of range - } - - wchar_t GetDecimalSeparator() const - { - return m_decimalSeparator; - } - - wchar_t GetNumberGroupSeparator() const - { - return m_numberGroupSeparator; - } - - std::wstring GetDecimalSeparatorStr() const - { - return std::wstring(1, m_decimalSeparator); - } - - std::wstring GetNumberGroupingSeparatorStr() const - { - return std::wstring(1, m_numberGroupSeparator); - } - - std::wstring GetNumberGroupingStr() const - { - return m_numberGrouping; - } - - Platform::String ^ RemoveGroupSeparators(Platform::String ^ source) const - { - std::wstring destination; - std::copy_if( - begin(source), end(source), std::back_inserter(destination), [this](auto const c) { return c != L' ' && c != m_numberGroupSeparator; }); - - return ref new Platform::String(destination.c_str()); - } - - Platform::String ^ GetCalendarIdentifier() const - { - return m_calendarIdentifier; - } - - std::wstring GetListSeparator() const - { - return m_listSeparator; - } - - Windows::Globalization::DayOfWeek GetFirstDayOfWeek() const - { - return m_firstDayOfWeek; - } - - int GetCurrencyTrailingDigits() const - { - return m_currencyTrailingDigits; - } - - int GetCurrencySymbolPrecedence() const - { - return m_currencySymbolPrecedence; - } - - private: static Platform::String^ GetCalendarIdentifierFromCalid(CALID calId) { switch (calId) diff --git a/src/CalcViewModel/Common/LocalizationStringUtil.h b/src/CalcViewModel/Common/LocalizationStringUtil.h index 73da6d0d..d7e08032 100644 --- a/src/CalcViewModel/Common/LocalizationStringUtil.h +++ b/src/CalcViewModel/Common/LocalizationStringUtil.h @@ -5,7 +5,7 @@ #include "AppResourceProvider.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { @@ -16,7 +16,7 @@ namespace CalculatorApp { std::wstring returnString = L""; const UINT32 length = 1024; - std::unique_ptr spBuffer = std::unique_ptr(new wchar_t[length]); + std::unique_ptr spBuffer = std::make_unique(length); va_list args = NULL; va_start(args, pMessage); DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pMessage->Data(), 0, 0, spBuffer.get(), length, &args); diff --git a/src/CalcViewModel/Common/MyVirtualKey.h b/src/CalcViewModel/Common/MyVirtualKey.h index c530e816..071b4183 100644 --- a/src/CalcViewModel/Common/MyVirtualKey.h +++ b/src/CalcViewModel/Common/MyVirtualKey.h @@ -3,7 +3,7 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { diff --git a/src/CalcViewModel/Common/NavCategory.cpp b/src/CalcViewModel/Common/NavCategory.cpp index 6a3c21b9..829f7488 100644 --- a/src/CalcViewModel/Common/NavCategory.cpp +++ b/src/CalcViewModel/Common/NavCategory.cpp @@ -8,11 +8,11 @@ #include using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel; using namespace Concurrency; using namespace Platform; using namespace Platform::Collections; -using namespace std; using namespace Windows::Foundation::Collections; using namespace Windows::Management::Policies; using namespace Windows::System; @@ -47,451 +47,236 @@ static constexpr int CURRENCY_ID = 16; static constexpr int GRAPHING_ID = 17; // ^^^ THESE CONSTANTS SHOULD NEVER CHANGE ^^^ -wchar_t* towchar_t(int number) +namespace // put the utils within this TU { - auto wstr = to_wstring(number); - return _wcsdup(wstr.c_str()); -} + Platform::String^ CurrentUserId; + std::mutex GraphingModeCheckMutex; -bool IsGraphingModeAvailable() -{ - static bool supportGraph = Windows::Foundation::Metadata::ApiInformation::IsMethodPresent("Windows.UI.Text.RichEditTextDocument", "GetMath"); - return supportGraph; -} - -Box ^ _isGraphingModeEnabledCached = nullptr; -bool IsGraphingModeEnabled(User ^ currentUser = nullptr) -{ - if (!IsGraphingModeAvailable()) + bool IsGraphingModeEnabled() { - return false; - } + static bool isChecked = false; + static bool isEnabled = false; - if (_isGraphingModeEnabledCached != nullptr) - { - return _isGraphingModeEnabledCached->Value; - } - - if (!currentUser) - { - return true; - } - - auto namedPolicyData = NamedPolicy::GetPolicyFromPathForUser(currentUser, L"Education", L"AllowGraphingCalculator"); - _isGraphingModeEnabledCached = namedPolicyData->GetBoolean() == true; - - return _isGraphingModeEnabledCached->Value; -} - -// The order of items in this list determines the order of items in the menu. -static list s_categoryManifest = [] { - auto res = list{ NavCategoryInitializer{ ViewMode::Standard, - STANDARD_ID, - L"Standard", - L"StandardMode", - L"\uE8EF", - CategoryGroupType::Calculator, - MyVirtualKey::Number1, - L"1", - SUPPORTS_ALL, - true }, - NavCategoryInitializer{ ViewMode::Scientific, - SCIENTIFIC_ID, - L"Scientific", - L"ScientificMode", - L"\uF196", - CategoryGroupType::Calculator, - MyVirtualKey::Number2, - L"2", - SUPPORTS_ALL, - true } }; - - int currentIndex = 3; - bool supportGraphingCalculator = IsGraphingModeAvailable(); - if (supportGraphingCalculator) - { - bool isEnabled = IsGraphingModeEnabled(); - res.push_back(NavCategoryInitializer{ ViewMode::Graphing, - GRAPHING_ID, - L"Graphing", - L"GraphingCalculatorMode", - L"\uF770", - CategoryGroupType::Calculator, - MyVirtualKey::Number3, - L"3", - SUPPORTS_ALL, - isEnabled }); - ++currentIndex; - } - res.insert( - res.end(), - { NavCategoryInitializer{ ViewMode::Programmer, - PROGRAMMER_ID, - L"Programmer", - L"ProgrammerMode", - L"\uECCE", - CategoryGroupType::Calculator, - supportGraphingCalculator ? MyVirtualKey::Number4 : MyVirtualKey::Number3, - towchar_t(currentIndex++), - SUPPORTS_ALL, - true }, - NavCategoryInitializer{ ViewMode::Date, - DATE_ID, - L"Date", - L"DateCalculationMode", - L"\uE787", - CategoryGroupType::Calculator, - supportGraphingCalculator ? MyVirtualKey::Number5 : MyVirtualKey::Number4, - towchar_t(currentIndex++), - SUPPORTS_ALL, - true }, - NavCategoryInitializer{ ViewMode::Currency, - CURRENCY_ID, - L"Currency", - L"CategoryName_Currency", - L"\uEB0D", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Volume, - VOLUME_ID, - L"Volume", - L"CategoryName_Volume", - L"\uF1AA", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Length, - LENGTH_ID, - L"Length", - L"CategoryName_Length", - L"\uECC6", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Weight, - WEIGHT_ID, - L"Weight and Mass", - L"CategoryName_Weight", - L"\uF4C1", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Temperature, - TEMPERATURE_ID, - L"Temperature", - L"CategoryName_Temperature", - L"\uE7A3", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - SUPPORTS_NEGATIVE, - true }, - NavCategoryInitializer{ ViewMode::Energy, - ENERGY_ID, - L"Energy", - L"CategoryName_Energy", - L"\uECAD", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Area, - AREA_ID, - L"Area", - L"CategoryName_Area", - L"\uE809", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Speed, - SPEED_ID, - L"Speed", - L"CategoryName_Speed", - L"\uEADA", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Time, - TIME_ID, - L"Time", - L"CategoryName_Time", - L"\uE917", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Power, - POWER_ID, - L"Power", - L"CategoryName_Power", - L"\uE945", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - SUPPORTS_NEGATIVE, - true }, - NavCategoryInitializer{ ViewMode::Data, - DATA_ID, - L"Data", - L"CategoryName_Data", - L"\uF20F", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Pressure, - PRESSURE_ID, - L"Pressure", - L"CategoryName_Pressure", - L"\uEC4A", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - POSITIVE_ONLY, - true }, - NavCategoryInitializer{ ViewMode::Angle, - ANGLE_ID, - L"Angle", - L"CategoryName_Angle", - L"\uF515", - CategoryGroupType::Converter, - MyVirtualKey::None, - nullptr, - SUPPORTS_NEGATIVE, - true } }); - return res; -}(); - -void NavCategory::InitializeCategoryManifest(User ^ user) -{ - int i = 0; - for (NavCategoryInitializer category : s_categoryManifest) - { - if (category.viewMode == ViewMode::Graphing) + std::scoped_lock lock(GraphingModeCheckMutex); + if (isChecked) { - auto navCatInit = s_categoryManifest.begin(); - std::advance(navCatInit, i); - (*navCatInit).isEnabled = IsGraphingModeEnabled(user); - break; + return isEnabled; } else { - i++; - } - } -} - -// This function should only be used when storing the mode to app data. -int NavCategory::Serialize(ViewMode mode) -{ - auto iter = - find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; }); - - return (iter != s_categoryManifest.end()) ? iter->serializationId : -1; -} - -// This function should only be used when restoring the mode from app data. -ViewMode NavCategory::Deserialize(Platform::Object ^ obj) -{ - // If we cast directly to ViewMode we will fail - // because we technically store an int. - // Need to cast to int, then ViewMode. - auto boxed = dynamic_cast ^>(obj); - if (boxed != nullptr) - { - int serializationId = boxed->Value; - auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [serializationId](const NavCategoryInitializer& initializer) { - return initializer.serializationId == serializationId; - }); - - if (iter != s_categoryManifest.end()) - { - if (iter->viewMode == ViewMode::Graphing) + auto user = User::GetFromId(CurrentUserId); + if (user == nullptr) { - // check if the user is allowed to use this feature - if (!IsGraphingModeEnabled()) - { - return ViewMode::None; - } + return true; } - return iter->viewMode; + + auto namedPolicyData = NamedPolicy::GetPolicyFromPathForUser( + user, + L"Education", + L"AllowGraphingCalculator"); + isEnabled = namedPolicyData->GetBoolean(); + isChecked = true; + return isEnabled; } } - return ViewMode::None; -} + // The order of items in this list determines the order of items in the menu. + const std::vector s_categoryManifest { + NavCategoryInitializer{ ViewMode::Standard, + STANDARD_ID, + L"Standard", + L"StandardMode", + L"\uE8EF", + CategoryGroupType::Calculator, + MyVirtualKey::Number1, + L"1", + SUPPORTS_ALL }, + NavCategoryInitializer{ ViewMode::Scientific, + SCIENTIFIC_ID, + L"Scientific", + L"ScientificMode", + L"\uF196", + CategoryGroupType::Calculator, + MyVirtualKey::Number2, + L"2", + SUPPORTS_ALL }, + NavCategoryInitializer{ ViewMode::Graphing, + GRAPHING_ID, + L"Graphing", + L"GraphingCalculatorMode", + L"\uF770", + CategoryGroupType::Calculator, + MyVirtualKey::Number3, + L"3", + SUPPORTS_ALL }, + NavCategoryInitializer{ ViewMode::Programmer, + PROGRAMMER_ID, + L"Programmer", + L"ProgrammerMode", + L"\uECCE", + CategoryGroupType::Calculator, + MyVirtualKey::Number4, + L"4", + SUPPORTS_ALL }, + NavCategoryInitializer{ ViewMode::Date, + DATE_ID, + L"Date", + L"DateCalculationMode", + L"\uE787", + CategoryGroupType::Calculator, + MyVirtualKey::Number5, + L"5", + SUPPORTS_ALL }, + NavCategoryInitializer{ ViewMode::Currency, + CURRENCY_ID, + L"Currency", + L"CategoryName_Currency", + L"\uEB0D", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Volume, + VOLUME_ID, + L"Volume", + L"CategoryName_Volume", + L"\uF1AA", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Length, + LENGTH_ID, + L"Length", + L"CategoryName_Length", + L"\uECC6", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Weight, + WEIGHT_ID, + L"Weight and Mass", + L"CategoryName_Weight", + L"\uF4C1", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Temperature, + TEMPERATURE_ID, + L"Temperature", + L"CategoryName_Temperature", + L"\uE7A3", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + SUPPORTS_NEGATIVE }, + NavCategoryInitializer{ ViewMode::Energy, + ENERGY_ID, + L"Energy", + L"CategoryName_Energy", + L"\uECAD", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Area, + AREA_ID, + L"Area", + L"CategoryName_Area", + L"\uE809", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Speed, + SPEED_ID, + L"Speed", + L"CategoryName_Speed", + L"\uEADA", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Time, + TIME_ID, + L"Time", + L"CategoryName_Time", + L"\uE917", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Power, + POWER_ID, + L"Power", + L"CategoryName_Power", + L"\uE945", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + SUPPORTS_NEGATIVE }, + NavCategoryInitializer{ ViewMode::Data, + DATA_ID, + L"Data", + L"CategoryName_Data", + L"\uF20F", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Pressure, + PRESSURE_ID, + L"Pressure", + L"CategoryName_Pressure", + L"\uEC4A", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + POSITIVE_ONLY }, + NavCategoryInitializer{ ViewMode::Angle, + ANGLE_ID, + L"Angle", + L"CategoryName_Angle", + L"\uF515", + CategoryGroupType::Converter, + MyVirtualKey::None, + std::nullopt, + SUPPORTS_NEGATIVE }, + }; +} // namespace unnamed -bool NavCategory::IsValidViewMode(ViewMode mode) -{ - auto iter = - find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; }); - return iter != s_categoryManifest.end(); -} - -bool NavCategory::IsViewModeEnabled(ViewMode mode) -{ - auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { - return initializer.viewMode == mode && initializer.isEnabled; - }); - - return iter != s_categoryManifest.end(); -} - -bool NavCategory::IsCalculatorViewMode(ViewMode mode) +bool NavCategory::IsCalculatorViewMode(ViewModeType mode) { // Historically, Calculator modes are Standard, Scientific, and Programmer. return !IsDateCalculatorViewMode(mode) && !IsGraphingCalculatorViewMode(mode) && IsModeInCategoryGroup(mode, CategoryGroupType::Calculator); } -bool NavCategory::IsGraphingCalculatorViewMode(ViewMode mode) +bool NavCategory::IsGraphingCalculatorViewMode(ViewModeType mode) { - return mode == ViewMode::Graphing; + return mode == ViewModeType::Graphing; } -bool NavCategory::IsDateCalculatorViewMode(ViewMode mode) +bool NavCategory::IsDateCalculatorViewMode(ViewModeType mode) { - return mode == ViewMode::Date; + return mode == ViewModeType::Date; } -bool NavCategory::IsConverterViewMode(ViewMode mode) +bool NavCategory::IsConverterViewMode(ViewModeType mode) { return IsModeInCategoryGroup(mode, CategoryGroupType::Converter); } -bool NavCategory::IsModeInCategoryGroup(ViewMode mode, CategoryGroupType type) +bool NavCategory::IsModeInCategoryGroup(ViewModeType mode, CategoryGroupType type) { - auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, type](const NavCategoryInitializer& initializer) { - return initializer.viewMode == mode && initializer.groupType == type; - }); - - return iter != s_categoryManifest.end(); -} - -String ^ NavCategory::GetFriendlyName(ViewMode mode) -{ - auto iter = - find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; }); - - return (iter != s_categoryManifest.end()) ? StringReference(iter->friendlyName) : L"None"; -} - -ViewMode NavCategory::GetViewModeForFriendlyName(String ^ name) -{ - auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [name](const NavCategoryInitializer& initializer) { - return wcscmp(initializer.friendlyName, name->Data()) == 0; - }); - - return (iter != s_categoryManifest.end()) ? iter->viewMode : ViewMode::None; -} - -String ^ NavCategory::GetNameResourceKey(ViewMode mode) -{ - auto iter = - find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; }); - - return (iter != s_categoryManifest.end()) ? StringReference(iter->nameResourceKey) + "Text" : nullptr; -} - -CategoryGroupType NavCategory::GetGroupType(ViewMode mode) -{ - auto iter = - find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; }); - - return (iter != s_categoryManifest.end()) ? iter->groupType : CategoryGroupType::None; -} - -// GetIndex is 0-based, GetPosition is 1-based -int NavCategory::GetIndex(ViewMode mode) -{ - int position = NavCategory::GetPosition(mode); - return max(-1, position - 1); -} - -int NavCategory::GetFlatIndex(ViewMode mode) -{ - int index = -1; - CategoryGroupType type = CategoryGroupType::None; - auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, &type, &index](const NavCategoryInitializer& initializer) { - index++; - if (initializer.groupType != type) - { - type = initializer.groupType; - index++; - } - - return initializer.viewMode == mode; - }); - - return (iter != s_categoryManifest.end()) ? index : -1; -} - -// GetIndex is 0-based, GetPosition is 1-based -int NavCategory::GetIndexInGroup(ViewMode mode, CategoryGroupType type) -{ - int index = -1; - auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, type, &index](const NavCategoryInitializer& initializer) { - if (initializer.groupType == type) - { - index++; - return initializer.viewMode == mode; - } - - return false; - }); - - return (iter != s_categoryManifest.end()) ? index : -1; -} - -// GetIndex is 0-based, GetPosition is 1-based -int NavCategory::GetPosition(ViewMode mode) -{ - int position = 0; - auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, &position](const NavCategoryInitializer& initializer) { - position++; - return initializer.viewMode == mode; - }); - - return (iter != s_categoryManifest.end()) ? position : -1; -} - -ViewMode NavCategory::GetViewModeForVirtualKey(MyVirtualKey virtualKey) -{ - auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [virtualKey](const NavCategoryInitializer& initializer) { - return initializer.virtualKey == virtualKey; - }); - - return (iter != s_categoryManifest.end()) ? iter->viewMode : ViewMode::None; -} - -vector NavCategory::GetCategoryAcceleratorKeys() -{ - vector accelerators{}; - for (auto category : s_categoryManifest) - { - if (category.virtualKey != MyVirtualKey::None) - { - accelerators.push_back(category.virtualKey); - } - } - - return accelerators; + return std::any_of( + s_categoryManifest.cbegin(), + s_categoryManifest.cend(), + [mode, type](const auto& initializer) { + return initializer.viewMode == mode && initializer.groupType == type; + }); } NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer) @@ -521,32 +306,225 @@ NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupIniti categoryName, categoryAutomationName, StringReference(categoryInitializer.glyph), - categoryInitializer.accessKey != nullptr ? ref new String(categoryInitializer.accessKey) + categoryInitializer.accessKey.has_value() ? ref new String(categoryInitializer.accessKey->c_str()) : resProvider->GetResourceString(nameResourceKey + "AccessKey"), groupMode, categoryInitializer.viewMode, categoryInitializer.supportsNegative, - categoryInitializer.isEnabled)); + categoryInitializer.viewMode != ViewMode::Graphing)); } } } -IObservableVector ^ NavCategoryGroup::CreateMenuOptions() +void NavCategoryStates::SetCurrentUser(Platform::String^ userId) +{ + std::scoped_lock lock(GraphingModeCheckMutex); + CurrentUserId = userId; +} + +IObservableVector ^ NavCategoryStates::CreateMenuOptions() { auto menuOptions = ref new Vector(); - menuOptions->Append(CreateCalculatorCategory()); - menuOptions->Append(CreateConverterCategory()); + menuOptions->Append(CreateCalculatorCategoryGroup()); + menuOptions->Append(CreateConverterCategoryGroup()); return menuOptions; } -NavCategoryGroup ^ NavCategoryGroup::CreateCalculatorCategory() +NavCategoryGroup ^ NavCategoryStates::CreateCalculatorCategoryGroup() { return ref new NavCategoryGroup( NavCategoryGroupInitializer{ CategoryGroupType::Calculator, L"CalculatorModeTextCaps", L"CalculatorModeText", L"CalculatorModePluralText" }); } -NavCategoryGroup ^ NavCategoryGroup::CreateConverterCategory() +NavCategoryGroup ^ NavCategoryStates::CreateConverterCategoryGroup() { return ref new NavCategoryGroup( NavCategoryGroupInitializer{ CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" }); } + +// This function should only be used when storing the mode to app data. +int NavCategoryStates::Serialize(ViewMode mode) +{ + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [mode](const auto& initializer) { return initializer.viewMode == mode; }); + + return (citer != s_categoryManifest.cend()) ? citer->serializationId : -1; +} + +// This function should only be used when restoring the mode from app data. +ViewMode NavCategoryStates::Deserialize(Platform::Object ^ obj) +{ + // If we cast directly to ViewMode we will fail + // because we technically store an int. + // Need to cast to int, then ViewMode. + auto boxed = dynamic_cast ^>(obj); + if (boxed != nullptr) + { + int serializationId = boxed->Value; + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [serializationId](const auto& initializer) { return initializer.serializationId == serializationId; }); + + return citer != s_categoryManifest.cend() ? + (citer->viewMode == ViewMode::Graphing ? + (IsGraphingModeEnabled() ? citer->viewMode : ViewMode::None) + : citer->viewMode) + : ViewMode::None; + } + else + { + return ViewMode::None; + } +} + +ViewMode NavCategoryStates::GetViewModeForFriendlyName(String ^ name) +{ + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [name](const auto& initializer) { return wcscmp(initializer.friendlyName, name->Data()) == 0; }); + + return (citer != s_categoryManifest.cend()) ? citer->viewMode : ViewMode::None; +} + +String ^ NavCategoryStates::GetFriendlyName(ViewMode mode) +{ + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [mode](const auto& initializer) { return initializer.viewMode == mode; }); + + return (citer != s_categoryManifest.cend()) ? StringReference(citer->friendlyName) : L"None"; +} + +String ^ NavCategoryStates::GetNameResourceKey(ViewMode mode) +{ + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [mode](const auto& initializer) { return initializer.viewMode == mode; }); + + return (citer != s_categoryManifest.cend()) ? StringReference(citer->nameResourceKey) + "Text" : nullptr; +} + +CategoryGroupType NavCategoryStates::GetGroupType(ViewMode mode) +{ + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [mode](const auto& initializer) { return initializer.viewMode == mode; }); + + return (citer != s_categoryManifest.cend()) ? citer->groupType : CategoryGroupType::None; +} + +// GetIndex is 0-based, GetPosition is 1-based +int NavCategoryStates::GetIndex(ViewMode mode) +{ + int position = GetPosition(mode); + return std::max(-1, position - 1); +} + +int NavCategoryStates::GetFlatIndex(ViewMode mode) +{ + int index = -1; + CategoryGroupType type = CategoryGroupType::None; + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [mode, &type, &index](const auto& initializer) { + ++index; + if (initializer.groupType != type) + { + type = initializer.groupType; + ++index; + } + return initializer.viewMode == mode; + }); + + return (citer != s_categoryManifest.cend()) ? index : -1; +} + +// GetIndex is 0-based, GetPosition is 1-based +int NavCategoryStates::GetIndexInGroup(ViewMode mode, CategoryGroupType type) +{ + int index = -1; + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [mode, type, &index](const auto& initializer) { + if (initializer.groupType == type) + { + ++index; + return initializer.viewMode == mode; + } + return false; + }); + + return (citer != s_categoryManifest.cend()) ? index : -1; +} + +// GetIndex is 0-based, GetPosition is 1-based +int NavCategoryStates::GetPosition(ViewMode mode) +{ + int position = 0; + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [mode, &position](const auto& initializer) { + ++position; + return initializer.viewMode == mode; + }); + + return (citer != s_categoryManifest.cend()) ? position : -1; +} + +ViewMode NavCategoryStates::GetViewModeForVirtualKey(MyVirtualKey virtualKey) +{ + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [virtualKey](const auto& initializer) { return initializer.virtualKey == virtualKey; }); + + return (citer != s_categoryManifest.end()) ? citer->viewMode : ViewMode::None; +} + +void NavCategoryStates::GetCategoryAcceleratorKeys(IVector ^ accelerators) +{ + if (accelerators != nullptr) + { + accelerators->Clear(); + for (const auto& category : s_categoryManifest) + { + if (category.virtualKey != MyVirtualKey::None) + { + accelerators->Append(category.virtualKey); + } + } + } +} + +bool NavCategoryStates::IsValidViewMode(ViewMode mode) +{ + const auto& citer = find_if( + cbegin(s_categoryManifest), + cend(s_categoryManifest), + [mode](const auto& initializer) { return initializer.viewMode == mode; }); + + return citer != s_categoryManifest.cend(); +} + +bool NavCategoryStates::IsViewModeEnabled(ViewMode mode) +{ + if (mode != ViewMode::Graphing) + { + return true; + } + else + { + return IsGraphingModeEnabled(); + } +} + diff --git a/src/CalcViewModel/Common/NavCategory.h b/src/CalcViewModel/Common/NavCategory.h index c0ce95f0..810ccbed 100644 --- a/src/CalcViewModel/Common/NavCategory.h +++ b/src/CalcViewModel/Common/NavCategory.h @@ -17,7 +17,7 @@ #include "Utils.h" #include "MyVirtualKey.h" -namespace CalculatorApp +namespace CalculatorApp::ViewModel { namespace Common { @@ -59,46 +59,21 @@ namespace CalculatorApp private struct NavCategoryInitializer { - constexpr NavCategoryInitializer( - ViewMode mode, - int id, - wchar_t const* name, - wchar_t const* nameKey, - wchar_t const* glyph, - CategoryGroupType group, - MyVirtualKey vKey, - wchar_t const* aKey, - bool categorySupportsNegative, - bool enabled) - : viewMode(mode) - , serializationId(id) - , friendlyName(name) - , nameResourceKey(nameKey) - , glyph(glyph) - , groupType(group) - , virtualKey(vKey) - , accessKey(aKey) - , supportsNegative(categorySupportsNegative) - , isEnabled(enabled) - { - } - - const ViewMode viewMode; - const int serializationId; - const wchar_t* const friendlyName; - const wchar_t* const nameResourceKey; - const wchar_t* const glyph; - const CategoryGroupType groupType; - const MyVirtualKey virtualKey; - const wchar_t* const accessKey; - const bool supportsNegative; - bool isEnabled; + ViewMode viewMode; + int serializationId; + const wchar_t* friendlyName; + const wchar_t* nameResourceKey; + const wchar_t* glyph; + CategoryGroupType groupType; + MyVirtualKey virtualKey; + std::optional accessKey; + bool supportsNegative; }; private struct NavCategoryGroupInitializer { - constexpr NavCategoryGroupInitializer(CategoryGroupType t, wchar_t const* h, wchar_t const* n, wchar_t const* a) + NavCategoryGroupInitializer(CategoryGroupType t, wchar_t const* h, wchar_t const* n, wchar_t const* a) : type(t) , headerResourceKey(h) , modeResourceKey(n) @@ -112,36 +87,85 @@ namespace CalculatorApp const wchar_t* automationResourceKey; }; - [Windows::UI::Xaml::Data::Bindable] public ref class NavCategory sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged + [Windows::UI::Xaml::Data::Bindable] + public ref class NavCategory sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged { + private: + using ViewModeType = ::CalculatorApp::ViewModel::Common::ViewMode; public: OBSERVABLE_OBJECT(); PROPERTY_R(Platform::String ^, Name); PROPERTY_R(Platform::String ^, AutomationName); PROPERTY_R(Platform::String ^, Glyph); - PROPERTY_R(ViewMode, Mode); + PROPERTY_R(ViewModeType, ViewMode); PROPERTY_R(Platform::String ^, AccessKey); PROPERTY_R(bool, SupportsNegative); - PROPERTY_R(bool, IsEnabled); + PROPERTY_RW(bool, IsEnabled); property Platform::String - ^ AutomationId { Platform::String ^ get() { return m_Mode.ToString(); } } + ^ AutomationId { Platform::String ^ get() { return m_ViewMode.ToString(); } } + static bool IsCalculatorViewMode(ViewModeType mode); + static bool IsGraphingCalculatorViewMode(ViewModeType mode); + static bool IsDateCalculatorViewMode(ViewModeType mode); + static bool IsConverterViewMode(ViewModeType mode); + + internal : NavCategory( + Platform::String ^ name, + Platform::String ^ automationName, + Platform::String ^ glyph, + Platform::String ^ accessKey, + Platform::String ^ mode, + ViewModeType viewMode, + bool supportsNegative, + bool isEnabled) + : m_Name(name) + , m_AutomationName(automationName) + , m_Glyph(glyph) + , m_AccessKey(accessKey) + , m_modeString(mode) + , m_ViewMode(viewMode) + , m_SupportsNegative(supportsNegative) + , m_IsEnabled(isEnabled) + { + } + + private: + static bool IsModeInCategoryGroup(ViewModeType mode, CategoryGroupType groupType); + + Platform::String ^ m_modeString; + }; + + [Windows::UI::Xaml::Data::Bindable] + public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged + { + internal: + NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer); + public: + OBSERVABLE_OBJECT(); + OBSERVABLE_PROPERTY_R(Platform::String ^, Name); + OBSERVABLE_PROPERTY_R(Platform::String ^, AutomationName); + OBSERVABLE_PROPERTY_R(CategoryGroupType, GroupType); + OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Categories); + }; + + public ref class NavCategoryStates sealed + { + public: + static void SetCurrentUser(Platform::String^ user); + static Windows::Foundation::Collections::IObservableVector ^ CreateMenuOptions(); + static NavCategoryGroup ^ CreateCalculatorCategoryGroup(); + static NavCategoryGroup ^ CreateConverterCategoryGroup(); + + static bool IsValidViewMode(ViewMode mode); + static bool IsViewModeEnabled(ViewMode mode); // For saving/restoring last mode used. static int Serialize(ViewMode mode); static ViewMode Deserialize(Platform::Object ^ obj); + + // Query properties from states static ViewMode GetViewModeForFriendlyName(Platform::String ^ name); - - static bool IsValidViewMode(ViewMode mode); - static bool IsViewModeEnabled(ViewMode mode); - static bool IsCalculatorViewMode(ViewMode mode); - static bool IsGraphingCalculatorViewMode(ViewMode mode); - static bool IsDateCalculatorViewMode(ViewMode mode); - static bool IsConverterViewMode(ViewMode mode); - - static void InitializeCategoryManifest(Windows::System::User ^ user); - static Platform::String ^ GetFriendlyName(ViewMode mode); static Platform::String ^ GetNameResourceKey(ViewMode mode); static CategoryGroupType GetGroupType(ViewMode mode); @@ -152,52 +176,9 @@ namespace CalculatorApp static int GetIndexInGroup(ViewMode mode, CategoryGroupType type); static int GetPosition(ViewMode mode); + // Virtual key related static ViewMode GetViewModeForVirtualKey(MyVirtualKey virtualKey); - - internal : NavCategory( - Platform::String ^ name, - Platform::String ^ automationName, - Platform::String ^ glyph, - Platform::String ^ accessKey, - Platform::String ^ mode, - ViewMode viewMode, - bool supportsNegative, - bool isEnabled) - : m_Name(name) - , m_AutomationName(automationName) - , m_Glyph(glyph) - , m_AccessKey(accessKey) - , m_modeString(mode) - , m_Mode(viewMode) - , m_SupportsNegative(supportsNegative) - , m_IsEnabled(isEnabled) - { - } - - static std::vector GetCategoryAcceleratorKeys(); - - private: - static bool IsModeInCategoryGroup(ViewMode mode, CategoryGroupType groupType); - - Platform::String ^ m_modeString; - }; - - [Windows::UI::Xaml::Data::Bindable] public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged - { - public: - OBSERVABLE_OBJECT(); - OBSERVABLE_PROPERTY_R(Platform::String ^, Name); - OBSERVABLE_PROPERTY_R(Platform::String ^, AutomationName); - OBSERVABLE_PROPERTY_R(CategoryGroupType, GroupType); - OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Categories); - - static Windows::Foundation::Collections::IObservableVector ^ CreateMenuOptions(); - - internal : static NavCategoryGroup ^ CreateCalculatorCategory(); - static NavCategoryGroup ^ CreateConverterCategory(); - - private: - NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer); + static void GetCategoryAcceleratorKeys(Windows::Foundation::Collections::IVector ^ resutls); }; } } diff --git a/src/CalcViewModel/Common/NetworkManager.cpp b/src/CalcViewModel/Common/NetworkManager.cpp index 8bf3835a..4f032d96 100644 --- a/src/CalcViewModel/Common/NetworkManager.cpp +++ b/src/CalcViewModel/Common/NetworkManager.cpp @@ -5,6 +5,8 @@ #include "NetworkManager.h" using namespace CalculatorApp; +using namespace CalculatorApp::ViewModel; +using namespace CalculatorApp::ViewModel::Common; using namespace Platform; using namespace Windows::Networking::Connectivity; diff --git a/src/CalcViewModel/Common/NetworkManager.h b/src/CalcViewModel/Common/NetworkManager.h index 51903d94..6bf7b7c1 100644 --- a/src/CalcViewModel/Common/NetworkManager.h +++ b/src/CalcViewModel/Common/NetworkManager.h @@ -3,7 +3,7 @@ #pragma once -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { public enum class NetworkAccessBehavior diff --git a/src/CalcViewModel/Common/NumberBase.h b/src/CalcViewModel/Common/NumberBase.h index 4e15efa1..6efb323b 100644 --- a/src/CalcViewModel/Common/NumberBase.h +++ b/src/CalcViewModel/Common/NumberBase.h @@ -2,7 +2,7 @@ // Licensed under the MIT License. #pragma once -namespace CalculatorApp::Common +namespace CalculatorApp::ViewModel::Common { public enum class NumberBase diff --git a/src/CalcViewModel/Common/RadixType.cpp b/src/CalcViewModel/Common/RadixType.cpp new file mode 100644 index 00000000..12b45371 --- /dev/null +++ b/src/CalcViewModel/Common/RadixType.cpp @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" +#include "RadixType.h" + +// export enum RadixType + diff --git a/src/CalcViewModel/Common/RadixType.h b/src/CalcViewModel/Common/RadixType.h new file mode 100644 index 00000000..de4bc8a8 --- /dev/null +++ b/src/CalcViewModel/Common/RadixType.h @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +namespace CalculatorApp::ViewModel +{ + namespace Common + { + // This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN + public enum class RadixType + { + Hex, + Decimal, + Octal, + Binary + }; + } +} diff --git a/src/CalcViewModel/Common/TraceLogger.cpp b/src/CalcViewModel/Common/TraceLogger.cpp index f58513de..f9268ddf 100644 --- a/src/CalcViewModel/Common/TraceLogger.cpp +++ b/src/CalcViewModel/Common/TraceLogger.cpp @@ -7,7 +7,8 @@ #include "CalculatorButtonUser.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel; using namespace TraceLogging; using namespace Concurrency; using namespace std; @@ -78,7 +79,7 @@ namespace CalculatorApp { auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); fields->AddString(StringReference(L"VisualState"), state); fields->AddBoolean(StringReference(L"IsAlwaysOnTop"), isAlwaysOnTop); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VISUAL_STATE_CHANGED), fields); @@ -93,18 +94,17 @@ namespace CalculatorApp } auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); fields->AddUInt64(StringReference(L"NumOfOpenWindows"), currentWindowCount); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_WINDOW_ON_CREATED), fields); } void TraceLogger::LogModeChange(ViewMode mode) { - if (NavCategory::IsValidViewMode(mode)) + if (NavCategoryStates::IsValidViewMode(mode)) { auto fields = ref new LoggingFields(); - ; - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_MODE_CHANGED), fields); } } @@ -112,7 +112,7 @@ namespace CalculatorApp void TraceLogger::LogHistoryItemLoad(ViewMode mode, int historyListSize, int loadedIndex) { auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); fields->AddInt32(StringReference(L"HistoryListSize"), historyListSize); fields->AddInt32(StringReference(L"HistoryItemIndex"), loadedIndex); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_HISTORY_ITEM_LOAD), fields); @@ -121,7 +121,7 @@ namespace CalculatorApp void TraceLogger::LogMemoryItemLoad(ViewMode mode, int memoryListSize, int loadedIndex) { auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); fields->AddInt32(StringReference(L"MemoryListSize"), memoryListSize); fields->AddInt32(StringReference(L"MemoryItemIndex"), loadedIndex); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_MEMORY_ITEM_LOAD), fields); @@ -130,7 +130,7 @@ namespace CalculatorApp void TraceLogger::LogError(ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString) { auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); fields->AddString(StringReference(L"FunctionName"), functionName); fields->AddString(StringReference(L"Message"), errorString); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields); @@ -139,7 +139,7 @@ namespace CalculatorApp void TraceLogger::LogStandardException(ViewMode mode, wstring_view functionName, const exception& e) { auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); fields->AddString(StringReference(L"FunctionName"), StringReference(functionName.data())); wstringstream exceptionMessage; exceptionMessage << e.what(); @@ -147,16 +147,21 @@ namespace CalculatorApp TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields); } - void TraceLogger::LogPlatformException(ViewMode mode, wstring_view functionName, Platform::Exception ^ e) + void TraceLogger::LogPlatformExceptionInfo(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ functionName, Platform::String^ message, int hresult) { auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); - fields->AddString(StringReference(L"FunctionName"), StringReference(functionName.data())); - fields->AddString(StringReference(L"Message"), e->Message); - fields->AddInt32(StringReference(L"HRESULT"), e->HResult); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); + fields->AddString(StringReference(L"FunctionName"), functionName); + fields->AddString(StringReference(L"Message"), message); + fields->AddInt32(StringReference(L"HRESULT"), hresult); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields); } + void TraceLogger::LogPlatformException(ViewMode mode, Platform::String ^ functionName, Platform::Exception ^ e) + { + LogPlatformExceptionInfo(mode, functionName, e->Message, e->HResult); + } + void TraceLogger::UpdateButtonUsage(NumbersAndOperatorsEnum button, ViewMode mode) { // IsProgrammerMode, IsScientificMode, IsStandardMode and None are not actual buttons, so ignore them @@ -217,7 +222,7 @@ namespace CalculatorApp Platform::String ^ buttonUsageString; for (size_t i = 0; i < buttonLog.size(); i++) { - buttonUsageString += NavCategory::GetFriendlyName(buttonLog[i].mode); + buttonUsageString += NavCategoryStates::GetFriendlyName(buttonLog[i].mode); buttonUsageString += "|"; buttonUsageString += buttonLog[i].button.ToString(); buttonUsageString += "|"; @@ -239,7 +244,7 @@ namespace CalculatorApp { const wchar_t* calculationType = AddSubtractMode ? L"AddSubtractMode" : L"DateDifferenceMode"; auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(ViewMode::Date)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(ViewMode::Date)); fields->AddString(StringReference(L"CalculationType"), StringReference(calculationType)); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_DATE_CALCULATION_MODE_USED), fields); } @@ -247,7 +252,7 @@ namespace CalculatorApp void TraceLogger::LogConverterInputReceived(ViewMode mode) { auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_CONVERTER_INPUT_RECEIVED), fields); } @@ -260,7 +265,7 @@ namespace CalculatorApp void TraceLogger::LogInputPasted(ViewMode mode) { auto fields = ref new LoggingFields(); - fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode)); + fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_INPUT_PASTED), fields); } diff --git a/src/CalcViewModel/Common/TraceLogger.h b/src/CalcViewModel/Common/TraceLogger.h index cef592e8..e82d3645 100644 --- a/src/CalcViewModel/Common/TraceLogger.h +++ b/src/CalcViewModel/Common/TraceLogger.h @@ -8,15 +8,15 @@ // A trace logging provider can only be instantiated and registered once per module. // This class implements a singleton model ensure that only one instance is created. -namespace CalculatorApp +namespace CalculatorApp::ViewModel::Common { struct ButtonLog { public: int count; - CalculatorApp::NumbersAndOperatorsEnum button; - CalculatorApp::Common::ViewMode mode; - ButtonLog(CalculatorApp::NumbersAndOperatorsEnum btn, CalculatorApp::Common::ViewMode vMode) + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum button; + CalculatorApp::ViewModel::Common::ViewMode mode; + ButtonLog(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum btn, CalculatorApp::ViewModel::Common::ViewMode vMode) { button = btn; mode = vMode; @@ -62,20 +62,20 @@ namespace CalculatorApp public: static TraceLogger ^ GetInstance(); - void LogModeChange(CalculatorApp::Common::ViewMode mode); - void LogHistoryItemLoad(CalculatorApp::Common::ViewMode mode, int historyListSize, int loadedIndex); - void LogMemoryItemLoad(CalculatorApp::Common::ViewMode mode, int memoryListSize, int loadedIndex); - void UpdateButtonUsage(CalculatorApp::NumbersAndOperatorsEnum button, CalculatorApp::Common::ViewMode mode); + void LogModeChange(CalculatorApp::ViewModel::Common::ViewMode mode); + void LogHistoryItemLoad(CalculatorApp::ViewModel::Common::ViewMode mode, int historyListSize, int loadedIndex); + void LogMemoryItemLoad(CalculatorApp::ViewModel::Common::ViewMode mode, int memoryListSize, int loadedIndex); + void UpdateButtonUsage(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum button, CalculatorApp::ViewModel::Common::ViewMode mode); void LogButtonUsage(); void LogDateCalculationModeUsed(bool AddSubtractMode); void UpdateWindowCount(uint64 windowCount); void DecreaseWindowCount(); bool IsWindowIdInLog(int windowId); - void LogVisualStateChanged(CalculatorApp::Common::ViewMode mode, Platform::String ^ state, bool isAlwaysOnTop); - void LogWindowCreated(CalculatorApp::Common::ViewMode mode, int windowId); - void LogConverterInputReceived(CalculatorApp::Common::ViewMode mode); + void LogVisualStateChanged(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ state, bool isAlwaysOnTop); + void LogWindowCreated(CalculatorApp::ViewModel::Common::ViewMode mode, int windowId); + void LogConverterInputReceived(CalculatorApp::ViewModel::Common::ViewMode mode); void LogNavBarOpened(); - void LogError(CalculatorApp::Common::ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString); + void LogError(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString); void LogShowHideButtonClicked(bool isHideButton); void LogGraphButtonClicked(GraphButton buttonName, GraphButtonValue buttonValue); void LogGraphLineStyleChanged(LineStyleType style); @@ -83,10 +83,12 @@ namespace CalculatorApp void LogVariableSettingsChanged(Platform::String ^ setting); void LogGraphSettingsChanged(GraphSettingsType settingsType, Platform::String ^ settingValue); void LogGraphTheme(Platform::String ^ graphTheme); + void LogInputPasted(CalculatorApp::ViewModel::Common::ViewMode mode); + void LogPlatformExceptionInfo(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ functionName, Platform::String ^ message, int hresult); + internal: - void LogStandardException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ const std::exception& e); - void LogPlatformException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ Platform::Exception ^ e); - void LogInputPasted(CalculatorApp::Common::ViewMode mode); + void LogPlatformException(CalculatorApp::ViewModel::Common::ViewMode mode, Platform::String ^ functionName, Platform::Exception ^ e); + void LogStandardException(CalculatorApp::ViewModel::Common::ViewMode mode, std::wstring_view functionName, _In_ const std::exception& e); private: // Create an instance of TraceLogger diff --git a/src/CalcViewModel/Common/Utils.cpp b/src/CalcViewModel/Common/Utils.cpp index 6bcc527d..daae9e86 100644 --- a/src/CalcViewModel/Common/Utils.cpp +++ b/src/CalcViewModel/Common/Utils.cpp @@ -6,13 +6,16 @@ // #include "pch.h" + +#include + #include "Utils.h" #include "Common/AppResourceProvider.h" #include "Common/ExpressionCommandSerializer.h" #include "Common/ExpressionCommandDeserializer.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace concurrency; using namespace Graphing::Renderer; using namespace Platform; @@ -168,18 +171,20 @@ void Utils::TrimBack(wstring& value) }).base(), value.end()); } -String^ Utils::EscapeHtmlSpecialCharacters(String^ originalString, shared_ptr> specialCharacters) +bool operator==(const Color& color1, const Color& color2) +{ + return equal_to()(color1, color2); +} + +bool operator!=(const Color& color1, const Color& color2) +{ + return !(color1 == color2); +} + +String^ CalculatorApp::ViewModel::Common::Utilities::EscapeHtmlSpecialCharacters(String^ originalString) { // Construct a default special characters if not provided. - if (specialCharacters == nullptr) - { - specialCharacters = make_shared>(); - specialCharacters->push_back(L'&'); - specialCharacters->push_back(L'\"'); - specialCharacters->push_back(L'\''); - specialCharacters->push_back(L'<'); - specialCharacters->push_back(L'>'); - } + const std::vector specialCharacters {L'&', L'\"', L'\'', L'<', L'>'}; bool replaceCharacters = false; const wchar_t* pCh; @@ -189,7 +194,7 @@ String^ Utils::EscapeHtmlSpecialCharacters(String^ originalString, shared_ptrData(); *pCh; pCh++) { - if (std::find(specialCharacters->begin(), specialCharacters->end(), *pCh) != specialCharacters->end()) + if (std::find(specialCharacters.begin(), specialCharacters.end(), *pCh) != specialCharacters.end()) { replaceCharacters = true; break; @@ -233,20 +238,15 @@ String^ Utils::EscapeHtmlSpecialCharacters(String^ originalString, shared_ptr()(color1, color2); -} - -bool operator!=(const Color& color1, const Color& color2) -{ - return !(color1 == color2); + return Utils::AreColorsEqual(color1, color2); } // This method calculates the luminance ratio between White and the given background color. // The luminance is calculate using the RGB values and does not use the A value. // White or Black is returned -SolidColorBrush ^ Utils::GetContrastColor(Color backgroundColor) +SolidColorBrush ^ CalculatorApp::ViewModel::Common::Utilities::GetContrastColor(Color backgroundColor) { auto luminance = 0.2126 * backgroundColor.R + 0.7152 * backgroundColor.G + 0.0722 * backgroundColor.B; @@ -257,3 +257,21 @@ SolidColorBrush ^ Utils::GetContrastColor(Color backgroundColor) return static_cast(Application::Current->Resources->Lookup(L"BlackBrush")); } + +int CalculatorApp::ViewModel::Common::Utilities::GetWindowId() +{ + return Utils::GetWindowId(); +} + +long long CalculatorApp::ViewModel::Common::Utilities::GetConst_WINEVENT_KEYWORD_RESPONSE_TIME() +{ + return WINEVENT_KEYWORD_RESPONSE_TIME; +} + +bool CalculatorApp::ViewModel::Common::Utilities::GetIntegratedDisplaySize(double* size) +{ + if (SUCCEEDED(::GetIntegratedDisplaySize(size))) + return true; + return false; +} + diff --git a/src/CalcViewModel/Common/Utils.h b/src/CalcViewModel/Common/Utils.h index 701969ea..8c3f5d2e 100644 --- a/src/CalcViewModel/Common/Utils.h +++ b/src/CalcViewModel/Common/Utils.h @@ -168,11 +168,22 @@ public: // The variable member generated by this macro should not be used in the class code, use the // property getter instead. #define COMMAND_FOR_METHOD(p, m) \ - property Windows::UI::Xaml::Input::ICommand^ p {\ - Windows::UI::Xaml::Input::ICommand^ get() {\ - if (!donotuse_##p) {\ - donotuse_##p = CalculatorApp::Common::MakeDelegate(this, &m);\ - } return donotuse_##p; }} private: Windows::UI::Xaml::Input::ICommand^ donotuse_##p; \ + property Windows::UI::Xaml::Input::ICommand ^ p \ + { \ + Windows::UI::Xaml::Input::ICommand ^ get() \ + { \ + if (!donotuse_##p) \ + { \ + donotuse_##p = ref new CalculatorApp::ViewModel::Common::DelegateCommand( \ + CalculatorApp::ViewModel::Common::MakeDelegateCommandHandler(this, &m) \ + ); \ + } \ + return donotuse_##p; \ + } \ + } \ + \ +private: \ + Windows::UI::Xaml::Input::ICommand ^ donotuse_##p; \ \ public: @@ -398,10 +409,6 @@ namespace Utils void Trim(std::wstring& value); void TrimFront(std::wstring& value); void TrimBack(std::wstring& value); - - Platform::String ^ EscapeHtmlSpecialCharacters(Platform::String ^ originalString, std::shared_ptr> specialCharacters = nullptr); - - Windows::UI::Xaml::Media::SolidColorBrush ^ GetContrastColor(Windows::UI::Color backgroundColor); } // This goes into the header to define the property, in the public: section of the class @@ -697,6 +704,22 @@ namespace CalculatorApp return to; } + + namespace ViewModel::Common + { + // below utilities are intended to support interops between C# and C++/CX + // they can be removed if the entire codebase has been migrated to C# + public ref class Utilities sealed + { + public: + static Platform::String ^ EscapeHtmlSpecialCharacters(Platform::String ^ originalString); + static bool AreColorsEqual(Windows::UI::Color color1, Windows::UI::Color color2); + static Windows::UI::Xaml::Media::SolidColorBrush ^ GetContrastColor(Windows::UI::Color backgroundColor); + static int GetWindowId(); + static long long GetConst_WINEVENT_KEYWORD_RESPONSE_TIME(); + static bool GetIntegratedDisplaySize(double* size); + }; + } } // There's no standard definition of equality for Windows::UI::Color structs. diff --git a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp index 5aa6a708..c0b3690a 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp +++ b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp @@ -11,11 +11,11 @@ #include "UnitConverterDataConstants.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::LocalizationServiceProperties; -using namespace CalculatorApp::DataLoaders; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::LocalizationServiceProperties; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace CalculatorApp::ViewModel; -using namespace CalculatorApp::ViewModel::CurrencyDataLoaderConstants; +using namespace CalculatorApp::ViewModel::DataLoaders::CurrencyDataLoaderConstants; using namespace concurrency; using namespace Platform; using namespace std; @@ -69,7 +69,7 @@ static constexpr auto DEFAULT_TO_CURRENCY = L"EUR"; namespace CalculatorApp { - namespace ViewModel + namespace ViewModel::DataLoaders { namespace UnitConverterResourceKeys { @@ -188,10 +188,9 @@ void CurrencyDataLoader::ResetLoadStatus() #pragma optimize("", off) // Turn off optimizations to work around DevDiv 393321 void CurrencyDataLoader::LoadData() { - RegisterForNetworkBehaviorChanges(); - if (!LoadFinished()) { + RegisterForNetworkBehaviorChanges(); create_task([this]() -> task { vector()>> loadFunctions = { [this]() { return TryLoadDataFromCacheAsync(); }, @@ -241,7 +240,7 @@ unordered_map CurrencyDataLoader: bool CurrencyDataLoader::SupportsCategory(const UCM::Category& target) { - static int currencyId = NavCategory::Serialize(ViewMode::Currency); + static int currencyId = NavCategoryStates::Serialize(ViewMode::Currency); return target.id == currencyId; } @@ -300,7 +299,7 @@ pair CurrencyDataLoader::GetCurrencyRatioEquality(_In_ const U double ratio = (iter2->second).ratio; double rounded = RoundCurrencyRatio(ratio); - auto digit = LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'1'); + auto digit = LocalizationSettings::GetInstance()->GetDigitSymbolFromEnUsDigit(L'1'); auto digitSymbol = ref new String(&digit, 1); auto roundedFormat = m_ratioFormatter->Format(rounded); diff --git a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h index 3216d63e..6ee878be 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h +++ b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h @@ -9,7 +9,7 @@ namespace CalculatorApp { - namespace ViewModel + namespace ViewModel::DataLoaders { public enum class CurrencyLoadStatus @@ -54,7 +54,9 @@ namespace CalculatorApp class CurrencyDataLoader : public UCM::IConverterDataLoader, public UCM::ICurrencyConverterDataLoader { public: - CurrencyDataLoader(_In_ std::unique_ptr client, const wchar_t* overrideLanguage = nullptr); + CurrencyDataLoader( + _In_ std::unique_ptr client, + const wchar_t* overrideLanguage = nullptr); ~CurrencyDataLoader(); bool LoadFinished(); @@ -82,7 +84,7 @@ namespace CalculatorApp std::future TryLoadDataFromWebOverrideAsync() override; // ICurrencyConverterDataLoader - void OnNetworkBehaviorChanged(CalculatorApp::NetworkAccessBehavior newBehavior); + void OnNetworkBehaviorChanged(CalculatorApp::ViewModel::Common::NetworkAccessBehavior newBehavior); private: void ResetLoadStatus(); @@ -112,7 +114,7 @@ namespace CalculatorApp private: Platform::String ^ m_responseLanguage; - std::unique_ptr m_client; + std::unique_ptr m_client; bool m_isRtlLanguage; @@ -130,8 +132,8 @@ namespace CalculatorApp CurrencyLoadStatus m_loadStatus; - CalculatorApp::NetworkManager ^ m_networkManager; - CalculatorApp::NetworkAccessBehavior m_networkAccessBehavior; + CalculatorApp::ViewModel::Common::NetworkManager ^ m_networkManager; + CalculatorApp::ViewModel::Common::NetworkAccessBehavior m_networkAccessBehavior; Windows::Foundation::EventRegistrationToken m_networkBehaviorToken; bool m_meteredOverrideSet; }; diff --git a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp index e9d42c6c..39786f32 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp +++ b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp @@ -11,6 +11,7 @@ #endif using namespace CalculatorApp::DataLoaders; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace Platform; using namespace std; using namespace Windows::Foundation; diff --git a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h index cfd10e7d..8f667c7c 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h +++ b/src/CalcViewModel/DataLoaders/CurrencyHttpClient.h @@ -7,7 +7,7 @@ namespace CalculatorApp { - namespace DataLoaders + namespace ViewModel::DataLoaders { class CurrencyHttpClient : public ICurrencyHttpClient { diff --git a/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h b/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h index 69f23f52..84104b7b 100644 --- a/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h +++ b/src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h @@ -5,7 +5,7 @@ namespace CalculatorApp { - namespace DataLoaders + namespace ViewModel::DataLoaders { class ICurrencyHttpClient { diff --git a/src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h b/src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h index 0d22a14a..33c94d62 100644 --- a/src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h +++ b/src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h @@ -3,7 +3,7 @@ namespace CalculatorApp { - namespace ViewModel + namespace ViewModel::Common { private enum UnitConverterUnits @@ -164,7 +164,8 @@ namespace CalculatorApp Data_Zetabits = UnitStart + 163, Data_Zetabytes = UnitStart + 164, Area_Pyeong = UnitStart + 165, - UnitEnd = Area_Pyeong + Energy_Kilowatthour = UnitStart + 166, + UnitEnd = Energy_Kilowatthour }; } } diff --git a/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp b/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp index 601b0112..9cb0e811 100644 --- a/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp +++ b/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp @@ -7,8 +7,8 @@ #include "UnitConverterDataConstants.h" #include "CurrencyDataLoader.h" -using namespace CalculatorApp::Common; -using namespace CalculatorApp::DataLoaders; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace std; @@ -53,7 +53,7 @@ bool UnitConverterDataLoader::SupportsCategory(const UCM::Category& target) GetCategories(supportedCategories); } - static int currencyId = NavCategory::Serialize(ViewMode::Currency); + static int currencyId = NavCategoryStates::Serialize(ViewMode::Currency); auto itr = find_if(supportedCategories->begin(), supportedCategories->end(), [&](const UCM::Category& category) { return currencyId != category.id && target.id == category.id; }); @@ -79,7 +79,7 @@ void UnitConverterDataLoader::LoadData() this->m_ratioMap->clear(); for (UCM::Category objectCategory : *m_categoryList) { - ViewMode categoryViewMode = NavCategory::Deserialize(objectCategory.id); + ViewMode categoryViewMode = NavCategoryStates::Deserialize(objectCategory.id); assert(NavCategory::IsConverterViewMode(categoryViewMode)); if (categoryViewMode == ViewMode::Currency) { @@ -148,11 +148,11 @@ void UnitConverterDataLoader::LoadData() void UnitConverterDataLoader::GetCategories(_In_ shared_ptr> categoriesList) { categoriesList->clear(); - auto converterCategory = NavCategoryGroup::CreateConverterCategory(); + auto converterCategory = NavCategoryStates::CreateConverterCategoryGroup(); for (auto const& category : converterCategory->Categories) { /* Id, CategoryName, SupportsNegative */ - categoriesList->emplace_back(NavCategory::Serialize(category->Mode), category->Name->Data(), category->SupportsNegative); + categoriesList->emplace_back(NavCategoryStates::Serialize(category->ViewMode), category->Name->Data(), category->SupportsNegative); } } @@ -358,6 +358,13 @@ void UnitConverterDataLoader::GetUnits(_In_ unordered_map> categoriesList); - void GetUnits(_In_ std::unordered_map>& unitMap); - void GetConversionData(_In_ std::unordered_map>& categoryToUnitConversionMap); - void - GetExplicitConversionData(_In_ std::unordered_map>& unitToUnitConversionList); + void GetUnits(_In_ std::unordered_map>& unitMap); + void GetConversionData(_In_ std::unordered_map>& categoryToUnitConversionMap); + void GetExplicitConversionData(_In_ std::unordered_map>& unitToUnitConversionList); std::wstring GetLocalizedStringName(_In_ Platform::String ^ stringId); diff --git a/src/CalcViewModel/DateCalculatorViewModel.cpp b/src/CalcViewModel/DateCalculatorViewModel.cpp index a34c1288..ff8e0d9c 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.cpp +++ b/src/CalcViewModel/DateCalculatorViewModel.cpp @@ -10,8 +10,8 @@ #include "Common/CopyPasteManager.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::DateCalculation; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::DateCalculation; using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace Platform::Collections; @@ -45,13 +45,13 @@ DateCalculatorViewModel::DateCalculatorViewModel() , m_StrDateResult(L"") , m_StrDateResultAutomationName(L"") { - const auto & localizationSettings = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizationSettings = LocalizationSettings::GetInstance(); // Initialize Date Output format instances - InitializeDateOutputFormats(localizationSettings.GetCalendarIdentifier()); + InitializeDateOutputFormats(localizationSettings->GetCalendarIdentifier()); // Initialize Date Calc engine - m_dateCalcEngine = ref new DateCalculationEngine(localizationSettings.GetCalendarIdentifier()); + m_dateCalcEngine = ref new DateCalculationEngine(localizationSettings->GetCalendarIdentifier()); // Initialize dates of DatePicker controls to today's date auto calendar = ref new Calendar(); // We force the timezone to UTC, in order to avoid being affected by Daylight Saving Time @@ -68,7 +68,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() // Initialize the list separator delimiter appended with a space at the end, e.g. ", " // This will be used for date difference formatting: Y years, M months, W weeks, D days - m_listSeparator = localizationSettings.GetListSeparator() + L" "; + m_listSeparator = localizationSettings->GetListSeparator() + L" "; // Initialize the output results UpdateDisplayResult(); @@ -77,7 +77,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() for (int i = 0; i <= c_maxOffsetValue; i++) { wstring numberStr(to_wstring(i)); - localizationSettings.LocalizeDisplayValue(&numberStr); + localizationSettings->LocalizeDisplayValue(&numberStr); m_offsetValues->Append(ref new String(numberStr.c_str())); } @@ -378,7 +378,7 @@ void DateCalculatorViewModel::OnCopyCommand(Platform::Object ^ parameter) String ^ DateCalculatorViewModel::GetLocalizedNumberString(int value) const { wstring numberStr(to_wstring(value)); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&numberStr); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&numberStr); return ref new String(numberStr.c_str()); } diff --git a/src/CalcViewModel/DateCalculatorViewModel.h b/src/CalcViewModel/DateCalculatorViewModel.h index 48573784..7d9ff0ab 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.h +++ b/src/CalcViewModel/DateCalculatorViewModel.h @@ -125,26 +125,26 @@ namespace CalculatorApp } } - property CalculatorApp::Common::DateCalculation::DateDifference DateDiffResult + property CalculatorApp::ViewModel::Common::DateCalculation::DateDifference DateDiffResult { - CalculatorApp::Common::DateCalculation::DateDifference get() + CalculatorApp::ViewModel::Common::DateCalculation::DateDifference get() { return m_dateDiffResult; } - void set(CalculatorApp::Common::DateCalculation::DateDifference value) + void set(CalculatorApp::ViewModel::Common::DateCalculation::DateDifference value) { m_dateDiffResult = value; UpdateDisplayResult(); } } - property CalculatorApp::Common::DateCalculation::DateDifference DateDiffResultInDays + property CalculatorApp::ViewModel::Common::DateCalculation::DateDifference DateDiffResultInDays { - CalculatorApp::Common::DateCalculation::DateDifference get() + CalculatorApp::ViewModel::Common::DateCalculation::DateDifference get() { return m_dateDiffResultInDays; } - void set(CalculatorApp::Common::DateCalculation::DateDifference value) + void set(CalculatorApp::ViewModel::Common::DateCalculation::DateDifference value) { m_dateDiffResultInDays = value; UpdateDisplayResult(); @@ -172,13 +172,13 @@ namespace CalculatorApp Windows::Foundation::DateTime m_toDate; Windows::Foundation::DateTime m_startDate; Windows::Foundation::DateTime m_dateResult; - CalculatorApp::Common::DateCalculation::DateDifference m_dateDiffResult; - CalculatorApp::Common::DateCalculation::DateDifference m_dateDiffResultInDays; + CalculatorApp::ViewModel::Common::DateCalculation::DateDifference m_dateDiffResult; + CalculatorApp::ViewModel::Common::DateCalculation::DateDifference m_dateDiffResultInDays; // Private members - CalculatorApp::Common::DateCalculation::DateCalculationEngine ^ m_dateCalcEngine; - CalculatorApp::Common::DateCalculation::DateUnit m_daysOutputFormat; - CalculatorApp::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat; + CalculatorApp::ViewModel::Common::DateCalculation::DateCalculationEngine ^ m_dateCalcEngine; + CalculatorApp::ViewModel::Common::DateCalculation::DateUnit m_daysOutputFormat; + CalculatorApp::ViewModel::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat; Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ m_dateTimeFormatter; std::wstring m_listSeparator; }; diff --git a/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp b/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp index 50592aa4..e7829c75 100644 --- a/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp +++ b/src/CalcViewModel/GraphingCalculator/EquationViewModel.cpp @@ -6,7 +6,7 @@ #include "CalcViewModel\Common\LocalizationSettings.h" #include "CalcViewModel\GraphingCalculatorEnums.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace Graphing; using namespace Platform; using namespace Platform::Collections; @@ -245,7 +245,7 @@ namespace CalculatorApp::ViewModel return; } - Platform::String ^ separator = ref new String(LocalizationSettings::GetInstance().GetListSeparator().c_str()); + Platform::String ^ separator = ref new String(LocalizationSettings::GetInstance()->GetListSeparator().c_str()); wstring error; if ((graphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::Domain) == KeyGraphFeaturesFlag::Domain) diff --git a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp index 3c7de353..4353777c 100644 --- a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp +++ b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp @@ -3,10 +3,9 @@ #include "pch.h" #include "GraphingSettingsViewModel.h" -#include using namespace CalculatorApp::ViewModel; -using namespace CalcManager::NumberFormattingUtils; +using namespace CalculatorApp::ViewModel::Common; using namespace GraphControl; using namespace std; using namespace Platform; @@ -54,21 +53,22 @@ void GraphingSettingsViewModel::InitRanges() m_XMaxValue = xMax; m_YMinValue = yMin; m_YMaxValue = yMax; - auto valueStr = to_wstring(m_XMinValue); - TrimTrailingZeros(valueStr); - XMin = ref new String(valueStr.c_str()); - valueStr = to_wstring(m_XMaxValue); - TrimTrailingZeros(valueStr); - XMax = ref new String(valueStr.c_str()); + std::wostringstream xMinStr; + xMinStr << m_XMinValue; + XMin = ref new String(xMinStr.str().c_str()); - valueStr = to_wstring(m_YMinValue); - TrimTrailingZeros(valueStr); - YMin = ref new String(valueStr.c_str()); + std::wostringstream xMaxStr; + xMaxStr << m_XMaxValue; + XMax = ref new String(xMaxStr.str().c_str()); - valueStr = to_wstring(m_YMaxValue); - TrimTrailingZeros(valueStr); - YMax = ref new String(valueStr.c_str()); + std::wostringstream yMinStr; + yMinStr << m_YMinValue; + YMin = ref new String(yMinStr.str().c_str()); + + std::wostringstream yMaxStr; + yMaxStr << m_YMaxValue; + YMax = ref new String(yMaxStr.str().c_str()); m_dontUpdateDisplayRange = false; } @@ -102,7 +102,7 @@ void GraphingSettingsViewModel::UpdateDisplayRange() m_Graph->SetDisplayRanges(m_XMinValue, m_XMaxValue, m_YMinValue, m_YMaxValue); - TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::Grid, L""); + CalculatorApp::ViewModel::Common::TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::Grid, L""); } bool GraphingSettingsViewModel::HasError() diff --git a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h index 6d6045c0..81bb77fb 100644 --- a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h +++ b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h @@ -51,21 +51,14 @@ namespace CalculatorApp::ViewModel m_XIsMinLastChanged = true; if (m_Graph != nullptr) { - try + std::wistringstream input(value->Data()); + double number; + if (input >> number && input.eof()) { - size_t sz; - auto number = std::stod(value->Data(), &sz); - if (value->Length() == sz) - { - m_Graph->XAxisMin = m_XMinValue = number; - XMinError = false; - } - else - { - XMinError = true; - } + m_Graph->XAxisMin = m_XMinValue = number; + XMinError = false; } - catch (...) + else { XMinError = true; } @@ -92,21 +85,14 @@ namespace CalculatorApp::ViewModel m_XIsMinLastChanged = false; if (m_Graph != nullptr) { - try + std::wistringstream input(value->Data()); + double number; + if (input >> number && input.eof()) { - size_t sz; - auto number = std::stod(value->Data(), &sz); - if (value->Length() == sz) - { - m_Graph->XAxisMax = m_XMaxValue = number; - XMaxError = false; - } - else - { - XMaxError = true; - } + m_Graph->XAxisMax = m_XMaxValue = number; + XMaxError = false; } - catch (...) + else { XMaxError = true; } @@ -133,21 +119,14 @@ namespace CalculatorApp::ViewModel m_YIsMinLastChanged = true; if (m_Graph != nullptr) { - try + std::wistringstream input(value->Data()); + double number; + if (input >> number && input.eof()) { - size_t sz; - auto number = std::stod(value->Data(), &sz); - if (value->Length() == sz) - { - m_Graph->YAxisMin = m_YMinValue = number; - YMinError = false; - } - else - { - YMinError = true; - } + m_Graph->YAxisMin = m_YMinValue = number; + YMinError = false; } - catch (...) + else { YMinError = true; } @@ -174,21 +153,14 @@ namespace CalculatorApp::ViewModel m_YIsMinLastChanged = false; if (m_Graph != nullptr) { - try + std::wistringstream input(value->Data()); + double number; + if (input >> number && input.eof()) { - size_t sz; - auto number = std::stod(value->Data(), &sz); - if (value->Length() == sz) - { - m_Graph->YAxisMax = m_YMaxValue = number; - YMaxError = false; - } - else - { - YMaxError = true; - } + m_Graph->YAxisMax = m_YMaxValue = number; + YMaxError = false; } - catch (...) + else { YMaxError = true; } @@ -232,7 +204,7 @@ namespace CalculatorApp::ViewModel RaisePropertyChanged(L"TrigModeDegrees"); RaisePropertyChanged(L"TrigModeGradians"); - TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits, L"Radians"); + CalculatorApp::ViewModel::Common::TraceLogger::GetInstance()->LogGraphSettingsChanged(CalculatorApp::ViewModel::Common::GraphSettingsType::TrigUnits, L"Radians"); } } } @@ -253,7 +225,7 @@ namespace CalculatorApp::ViewModel RaisePropertyChanged(L"TrigModeRadians"); RaisePropertyChanged(L"TrigModeGradians"); - TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits, L"Degrees"); + CalculatorApp::ViewModel::Common::TraceLogger::GetInstance()->LogGraphSettingsChanged(CalculatorApp::ViewModel::Common::GraphSettingsType::TrigUnits, L"Degrees"); } } } @@ -274,7 +246,7 @@ namespace CalculatorApp::ViewModel RaisePropertyChanged(L"TrigModeDegrees"); RaisePropertyChanged(L"TrigModeRadians"); - TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits, L"Gradians"); + CalculatorApp::ViewModel::Common::TraceLogger::GetInstance()->LogGraphSettingsChanged(CalculatorApp::ViewModel::Common::GraphSettingsType::TrigUnits, L"Gradians"); } } } diff --git a/src/CalcViewModel/GraphingCalculator/VariableViewModel.h b/src/CalcViewModel/GraphingCalculator/VariableViewModel.h index 151499ec..6c15fba3 100644 --- a/src/CalcViewModel/GraphingCalculator/VariableViewModel.h +++ b/src/CalcViewModel/GraphingCalculator/VariableViewModel.h @@ -127,8 +127,8 @@ public { Platform::String ^ get() { - return CalculatorApp::Common::LocalizationStringUtil::GetLocalizedString( - CalculatorApp::AppResourceProvider::GetInstance()->GetResourceString(L"VariableListViewItem"), Name); + return CalculatorApp::ViewModel::Common::LocalizationStringUtil::GetLocalizedString( + CalculatorApp::ViewModel::Common::AppResourceProvider::GetInstance()->GetResourceString(L"VariableListViewItem"), Name); } } diff --git a/src/CalcViewModel/HistoryItemViewModel.cpp b/src/CalcViewModel/HistoryItemViewModel.cpp index 95775bb9..023ab643 100644 --- a/src/CalcViewModel/HistoryItemViewModel.cpp +++ b/src/CalcViewModel/HistoryItemViewModel.cpp @@ -5,7 +5,7 @@ #include "HistoryItemViewModel.h" #include "Common/LocalizationService.h" -using namespace CalculatorApp::Common; +using namespace CalculatorApp::ViewModel::Common; using namespace CalculatorApp::ViewModel; using namespace std; using namespace Platform; diff --git a/src/CalcViewModel/HistoryViewModel.cpp b/src/CalcViewModel/HistoryViewModel.cpp index 8235c93a..0953486d 100644 --- a/src/CalcViewModel/HistoryViewModel.cpp +++ b/src/CalcViewModel/HistoryViewModel.cpp @@ -9,8 +9,8 @@ #include "StandardCalculatorViewModel.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace std; @@ -57,15 +57,15 @@ void HistoryViewModel::ReloadHistory(_In_ ViewMode currentMode) auto historyListModel = m_calculatorManager->GetHistoryItems(m_currentMode); auto historyListVM = ref new Platform::Collections::Vector(); - const auto& localizer = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); if (historyListModel.size() > 0) { for (auto ritr = historyListModel.rbegin(); ritr != historyListModel.rend(); ++ritr) { wstring expression = (*ritr)->historyItemVector.expression; wstring result = (*ritr)->historyItemVector.result; - localizer.LocalizeDisplayValue(&expression); - localizer.LocalizeDisplayValue(&result); + localizer->LocalizeDisplayValue(&expression); + localizer->LocalizeDisplayValue(&result); auto item = ref new HistoryItemViewModel( ref new Platform::String(expression.c_str()), @@ -83,11 +83,11 @@ void HistoryViewModel::ReloadHistory(_In_ ViewMode currentMode) void HistoryViewModel::OnHistoryItemAdded(_In_ unsigned int addedItemIndex) { auto newItem = m_calculatorManager->GetHistoryItem(addedItemIndex); - const auto& localizer = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); wstring expression = newItem->historyItemVector.expression; wstring result = newItem->historyItemVector.result; - localizer.LocalizeDisplayValue(&expression); - localizer.LocalizeDisplayValue(&result); + localizer->LocalizeDisplayValue(&expression); + localizer->LocalizeDisplayValue(&result); auto item = ref new HistoryItemViewModel( ref new Platform::String(expression.c_str()), ref new Platform::String(result.c_str()), @@ -133,7 +133,7 @@ void HistoryViewModel::DeleteItem(_In_ HistoryItemViewModel ^ e) } // Adding 1 to the history item index to provide 1-based numbering on announcements. wstring localizedIndex = to_wstring(itemIndex + 1); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedIndex); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&localizedIndex); m_localizedHistorySlotCleared = AppResourceProvider::GetInstance()->GetResourceString(HistoryResourceKeys::HistorySlotCleared); String ^ announcement = LocalizationStringUtil::GetLocalizedString(m_localizedHistorySlotCleared, StringReference(localizedIndex.c_str())); HistoryAnnouncement = CalculatorAnnouncement::GetHistorySlotClearedAnnouncement(announcement); diff --git a/src/CalcViewModel/HistoryViewModel.h b/src/CalcViewModel/HistoryViewModel.h index d7c7874e..a09360ed 100644 --- a/src/CalcViewModel/HistoryViewModel.h +++ b/src/CalcViewModel/HistoryViewModel.h @@ -28,7 +28,7 @@ namespace CalculatorApp OBSERVABLE_OBJECT(); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Items); OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled); - OBSERVABLE_PROPERTY_R(CalculatorApp::Common::Automation::NarratorAnnouncement ^, HistoryAnnouncement); + OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^, HistoryAnnouncement); property int ItemsCount { int get() @@ -48,17 +48,17 @@ namespace CalculatorApp event HideHistoryClickedHandler ^ HideHistoryClicked; event HistoryItemClickedHandler ^ HistoryItemClicked; void ShowItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel ^ e); + void DeleteItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel ^ e); + void ReloadHistory(_In_ CalculatorApp::ViewModel::Common::ViewMode currentMode); internal : HistoryViewModel(_In_ CalculationManager::CalculatorManager* calculatorManager); - void SetCalculatorDisplay(CalculatorDisplay& calculatorDisplay); - void ReloadHistory(_In_ CalculatorApp::Common::ViewMode currentMode); + void SetCalculatorDisplay(Common::CalculatorDisplay& calculatorDisplay); unsigned long long GetMaxItemSize(); - void DeleteItem(_In_ CalculatorApp::ViewModel::HistoryItemViewModel ^ e); private: CalculationManager::CalculatorManager* const m_calculatorManager; - CalculatorDisplay m_calculatorDisplay; + Common::CalculatorDisplay m_calculatorDisplay; CalculationManager::CalculatorMode m_currentMode; Platform::String ^ m_localizedHistoryCleared; Platform::String ^ m_localizedHistorySlotCleared; diff --git a/src/CalcViewModel/MemoryItemViewModel.cpp b/src/CalcViewModel/MemoryItemViewModel.cpp index b7d21649..9600e773 100644 --- a/src/CalcViewModel/MemoryItemViewModel.cpp +++ b/src/CalcViewModel/MemoryItemViewModel.cpp @@ -6,8 +6,8 @@ #include "StandardCalculatorViewModel.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace CalculatorApp::ViewModel; using namespace Platform; using namespace std; diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index 56f2bda4..22554ca6 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -10,8 +10,8 @@ #include "Common/TraceLogger.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::Automation; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::Automation; using namespace CalculatorApp::ViewModel; using namespace CalculationManager; using namespace concurrency; @@ -25,7 +25,6 @@ using namespace Windows::UI::Core; using namespace Windows::UI::Popups; using namespace Windows::Storage::Streams; using namespace Windows::Foundation::Collections; -using namespace Utils; using namespace concurrency; constexpr int StandardModePrecision = 16; @@ -118,7 +117,7 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() m_HistoryVM = ref new HistoryViewModel(&m_standardCalculatorManager); m_HistoryVM->SetCalculatorDisplay(m_calculatorDisplay); - m_decimalSeparator = LocalizationSettings::GetInstance().GetDecimalSeparator(); + m_decimalSeparator = LocalizationSettings::GetInstance()->GetDecimalSeparator(); if (CoreWindow::GetForCurrentThread() != nullptr) { @@ -138,7 +137,14 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() String ^ StandardCalculatorViewModel::LocalizeDisplayValue(_In_ wstring const& displayValue) { wstring result(displayValue); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&result); + + // Adds leading padding 0's to Programmer Mode's Binary Display + if (IsProgrammer && CurrentRadixType == NumberBase::BinBase) + { + result = AddPadding(result); + } + + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&result); return ref new Platform::String(result.c_str()); } @@ -170,13 +176,13 @@ String ^ StandardCalculatorViewModel::CalculateNarratorDisplayValue(_In_ wstring String ^ StandardCalculatorViewModel::GetNarratorStringReadRawNumbers(_In_ String ^ localizedDisplayValue) { wstring ws; - const auto& locSettings = LocalizationSettings::GetInstance(); + LocalizationSettings^ locSettings = LocalizationSettings::GetInstance(); // Insert a space after each digit in the string, to force Narrator to read them as separate numbers. for (const wchar_t& c : localizedDisplayValue) { ws += c; - if (locSettings.IsLocalizedHexDigit(c)) + if (locSettings->IsLocalizedHexDigit(c)) { ws += L' '; } @@ -230,7 +236,7 @@ void StandardCalculatorViewModel::SetParenthesisCount(_In_ unsigned int parenthe void StandardCalculatorViewModel::SetOpenParenthesisCountNarratorAnnouncement() { wstring localizedParenthesisCount = to_wstring(m_OpenParenthesisCount).c_str(); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedParenthesisCount); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&localizedParenthesisCount); if (m_localizedOpenParenthesisCountChangedAutomationFormat == nullptr) { @@ -329,7 +335,7 @@ void StandardCalculatorViewModel::SetTokens(_Inout_ shared_ptrLocalizeDisplayValue(&(currentToken.first)); if (!isEditable) { @@ -392,7 +398,7 @@ String ^ StandardCalculatorViewModel::GetCalculatorExpressionAutomationName() void StandardCalculatorViewModel::SetMemorizedNumbers(const vector& newMemorizedNumbers) { - const auto& localizer = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); if (newMemorizedNumbers.size() == 0) // Memory has been cleared { MemorizedNumbers->Clear(); @@ -408,7 +414,7 @@ void StandardCalculatorViewModel::SetMemorizedNumbers(const vector& new MemoryItemViewModel ^ memorySlot = ref new MemoryItemViewModel(this); memorySlot->Position = 0; - localizer.LocalizeDisplayValue(&stringValue); + localizer->LocalizeDisplayValue(&stringValue); memorySlot->Value = ref new String(stringValue.c_str()); MemorizedNumbers->InsertAt(0, memorySlot); @@ -426,7 +432,7 @@ void StandardCalculatorViewModel::SetMemorizedNumbers(const vector& new for (unsigned int i = 0; i < MemorizedNumbers->Size; i++) { auto newStringValue = newMemorizedNumbers.at(i); - localizer.LocalizeDisplayValue(&newStringValue); + localizer->LocalizeDisplayValue(&newStringValue); // If the value is different, update the value if (MemorizedNumbers->GetAt(i)->Value != StringReference(newStringValue.c_str())) @@ -720,7 +726,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter) } // Ensure that the paste happens on the UI thread - create_task(CopyPasteManager::GetStringToPaste(mode, NavCategory::GetGroupType(mode), numberBase, bitLengthType)) + create_task(CopyPasteManager::GetStringToPaste(mode, NavCategoryStates::GetGroupType(mode), numberBase, bitLengthType)) .then([that, mode](String ^ pastedString) { that->OnPaste(pastedString); }, concurrency::task_continuation_context::use_current()); } @@ -1001,10 +1007,10 @@ ButtonInfo StandardCalculatorViewModel::MapCharacterToButtonId(char16 ch) if (result.buttonId == NumbersAndOperatorsEnum::None) { - if (LocalizationSettings::GetInstance().IsLocalizedDigit(ch)) + if (LocalizationSettings::GetInstance()->IsLocalizedDigit(ch)) { result.buttonId = - NumbersAndOperatorsEnum::Zero + static_cast(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit('0')); + NumbersAndOperatorsEnum::Zero + static_cast(ch - LocalizationSettings::GetInstance()->GetDigitSymbolFromEnUsDigit('0')); result.canSendNegate = true; } } @@ -1044,7 +1050,7 @@ void StandardCalculatorViewModel::OnMemoryItemChanged(unsigned int indexOfMemory String ^ localizedValue = memSlot->Value; wstring localizedIndex = to_wstring(indexOfMemory + 1); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedIndex); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&localizedIndex); if (m_localizedMemoryItemChangedAutomationFormat == nullptr) { @@ -1116,7 +1122,7 @@ void StandardCalculatorViewModel::OnMemoryClear(_In_ Object ^ memoryItemPosition TraceLogger::GetInstance()->UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryClear, GetCalculatorMode()); wstring localizedIndex = to_wstring(boxedPosition->Value + 1); - LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedIndex); + LocalizationSettings::GetInstance()->LocalizeDisplayValue(&localizedIndex); if (m_localizedMemoryItemClearedAutomationFormat == nullptr) { @@ -1189,20 +1195,20 @@ void StandardCalculatorViewModel::SetCalculatorType(ViewMode targetState) { case ViewMode::Standard: IsStandard = true; - ResetDisplay(); + ResetRadixAndUpdateMemory(true); SetPrecision(StandardModePrecision); UpdateMaxIntDigits(); break; case ViewMode::Scientific: IsScientific = true; - ResetDisplay(); + ResetRadixAndUpdateMemory(true); SetPrecision(ScientificModePrecision); break; case ViewMode::Programmer: IsProgrammer = true; - ResetDisplay(); + ResetRadixAndUpdateMemory(false); SetPrecision(ProgrammerModePrecision); break; } @@ -1216,7 +1222,7 @@ String ^ StandardCalculatorViewModel::GetRawDisplayValue() } else { - return LocalizationSettings::GetInstance().RemoveGroupSeparators(DisplayValue); + return LocalizationSettings::GetInstance()->RemoveGroupSeparators(DisplayValue); } } @@ -1228,11 +1234,18 @@ String ^ StandardCalculatorViewModel::GetLocalizedStringFormat(String ^ format, return LocalizationStringUtil::GetLocalizedString(format, displayValue); } -void StandardCalculatorViewModel::ResetDisplay() +void StandardCalculatorViewModel::ResetRadixAndUpdateMemory(bool resetRadix) { - AreHEXButtonsEnabled = false; - CurrentRadixType = NumberBase::DecBase; - m_standardCalculatorManager.SetRadix(RadixType::Decimal); + if (resetRadix) + { + AreHEXButtonsEnabled = false; + CurrentRadixType = NumberBase::DecBase; + m_standardCalculatorManager.SetRadix(RadixType::Decimal); + } + else + { + m_standardCalculatorManager.SetMemorizedNumbersString(); + } } void StandardCalculatorViewModel::SetPrecision(int32_t precision) @@ -1535,7 +1548,7 @@ size_t StandardCalculatorViewModel::LengthWithoutPadding(wstring str) wstring StandardCalculatorViewModel::AddPadding(wstring binaryString) { - if (LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(StringReference(binaryString.c_str())) == L"0") + if (LocalizationSettings::GetInstance()->GetEnglishValueFromLocalizedDigits(StringReference(binaryString.c_str())) == L"0") { return binaryString; } @@ -1571,13 +1584,13 @@ void StandardCalculatorViewModel::UpdateProgrammerPanelDisplay() binaryDisplayString = m_standardCalculatorManager.GetResultForRadix(2, precision, true); } } - const auto& localizer = LocalizationSettings::GetInstance(); + LocalizationSettings^ localizer = LocalizationSettings::GetInstance(); binaryDisplayString = AddPadding(binaryDisplayString); - localizer.LocalizeDisplayValue(&hexDisplayString); - localizer.LocalizeDisplayValue(&decimalDisplayString); - localizer.LocalizeDisplayValue(&octalDisplayString); - localizer.LocalizeDisplayValue(&binaryDisplayString); + localizer->LocalizeDisplayValue(&hexDisplayString); + localizer->LocalizeDisplayValue(&decimalDisplayString); + localizer->LocalizeDisplayValue(&octalDisplayString); + localizer->LocalizeDisplayValue(&binaryDisplayString); HexDisplayValue = ref new Platform::String(hexDisplayString.c_str()); DecimalDisplayValue = ref new Platform::String(decimalDisplayString.c_str()); @@ -1609,7 +1622,7 @@ void StandardCalculatorViewModel::UpdateOperand(int pos, String ^ text) { pair p = m_tokens->at(pos); - String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(text); + String ^ englishString = LocalizationSettings::GetInstance()->GetEnglishValueFromLocalizedDigits(text); p.first = englishString->Data(); int commandPos = p.second; @@ -1719,7 +1732,7 @@ ViewMode StandardCalculatorViewModel::GetCalculatorMode() return ViewMode::Programmer; } -void StandardCalculatorViewModel::ValueBitLength::set(CalculatorApp::Common::BitLength value) +void StandardCalculatorViewModel::ValueBitLength::set(CalculatorApp::ViewModel::Common::BitLength value) { if (m_valueBitLength != value) { diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index d60122bf..0af82478 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -29,7 +29,7 @@ namespace CalculatorApp public value struct ButtonInfo { - NumbersAndOperatorsEnum buttonId; + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum buttonId; bool canSendNegate; }; @@ -73,12 +73,12 @@ namespace CalculatorApp OBSERVABLE_PROPERTY_R(Platform::String ^, CalculationResultAutomationName); OBSERVABLE_PROPERTY_R(Platform::String ^, CalculationExpressionAutomationName); OBSERVABLE_PROPERTY_R(bool, IsShiftProgrammerChecked); - OBSERVABLE_PROPERTY_R(CalculatorApp::Common::NumberBase, CurrentRadixType); + OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Common::NumberBase, CurrentRadixType); OBSERVABLE_PROPERTY_R(bool, AreTokensUpdated); OBSERVABLE_PROPERTY_R(bool, AreAlwaysOnTopResultsUpdated); OBSERVABLE_PROPERTY_R(bool, AreProgrammerRadixOperatorsVisible); OBSERVABLE_PROPERTY_R(bool, IsInputEmpty); - OBSERVABLE_PROPERTY_R(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement); + OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^, Announcement); OBSERVABLE_PROPERTY_R(unsigned int, OpenParenthesisCount); COMMAND_FOR_METHOD(CopyCommand, StandardCalculatorViewModel::OnCopyCommand); @@ -111,13 +111,13 @@ namespace CalculatorApp static property Platform::String ^ IsBitFlipCheckedPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsBitFlipChecked"); } } - property CalculatorApp::Common::BitLength ValueBitLength + property CalculatorApp::ViewModel::Common::BitLength ValueBitLength { - CalculatorApp::Common::BitLength get() + CalculatorApp::ViewModel::Common::BitLength get() { return m_valueBitLength; } - void set(CalculatorApp::Common::BitLength value); + void set(CalculatorApp::ViewModel::Common::BitLength value); } property bool IsStandard @@ -244,6 +244,21 @@ namespace CalculatorApp void ResetCalcManager(bool clearMemory); void SendCommandToCalcManager(int command); + public: + // Memory feature related methods. + void OnMemoryButtonPressed(); + void OnMemoryItemPressed(Platform::Object ^ memoryItemPosition); + void OnMemoryAdd(Platform::Object ^ memoryItemPosition); + void OnMemorySubtract(Platform::Object ^ memoryItemPosition); + void OnMemoryClear(_In_ Platform::Object ^ memoryItemPosition); + + void SelectHistoryItem(HistoryItemViewModel ^ item); + void SwitchProgrammerModeBase(CalculatorApp::ViewModel::Common::NumberBase calculatorBase); + void SetBitshiftRadioButtonCheckedAnnouncement(Platform::String ^ announcement); + void SetOpenParenthesisCountNarratorAnnouncement(); + void SwitchAngleType(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum num); + void FtoEButtonToggled(); + internal: void OnPaste(Platform::String ^ pastedString); void OnCopyCommand(Platform::Object ^ parameter); @@ -251,47 +266,35 @@ namespace CalculatorApp ButtonInfo MapCharacterToButtonId(char16 ch); - // Memory feature related methods. They are internal because they need to called from the MainPage code-behind - void OnMemoryButtonPressed(); - void OnMemoryItemPressed(Platform::Object ^ memoryItemPosition); - void OnMemoryAdd(Platform::Object ^ memoryItemPosition); - void OnMemorySubtract(Platform::Object ^ memoryItemPosition); - void OnMemoryClear(_In_ Platform::Object ^ memoryItemPosition); - void OnInputChanged(); void DisplayPasteError(); void SetParenthesisCount(_In_ unsigned int parenthesisCount); - void SetOpenParenthesisCountNarratorAnnouncement(); void OnNoRightParenAdded(); void SetNoParenAddedNarratorAnnouncement(); void OnMaxDigitsReached(); void OnBinaryOperatorReceived(); void OnMemoryItemChanged(unsigned int indexOfMemory); - void SetBitshiftRadioButtonCheckedAnnouncement(Platform::String ^ announcement); Platform::String ^ GetLocalizedStringFormat(Platform::String ^ format, Platform::String ^ displayValue); void OnPropertyChanged(Platform::String ^ propertyname); - void SetCalculatorType(CalculatorApp::Common::ViewMode targetState); + void SetCalculatorType(CalculatorApp::ViewModel::Common::ViewMode targetState); Platform::String ^ GetRawDisplayValue(); void Recalculate(bool fromHistory = false); bool IsOperator(CalculationManager::Command cmdenum); - void FtoEButtonToggled(); - void SwitchProgrammerModeBase(CalculatorApp::Common::NumberBase calculatorBase); - void SetMemorizedNumbersString(); - void SwitchAngleType(NumbersAndOperatorsEnum num); - void ResetDisplay(); + void SetMemorizedNumbersString(); + void ResetRadixAndUpdateMemory(bool resetRadix); void SetPrecision(int32_t precision); void UpdateMaxIntDigits() { m_standardCalculatorManager.UpdateMaxIntDigits(); } - NumbersAndOperatorsEnum GetCurrentAngleType() + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum GetCurrentAngleType() { return m_CurrentAngleType; } - void SelectHistoryItem(HistoryItemViewModel ^ item); + private: void SetMemorizedNumbers(const std::vector& memorizedNumbers); void UpdateProgrammerPanelDisplay(); @@ -304,12 +307,12 @@ namespace CalculatorApp _Inout_ std::shared_ptr>> const& tokens, _Inout_ std::shared_ptr>> const& commands); void SetTokens(_Inout_ std::shared_ptr>> const& tokens); - NumbersAndOperatorsEnum ConvertIntegerToNumbersAndOperatorsEnum(unsigned int parameter); - static RadixType GetRadixTypeFromNumberBase(CalculatorApp::Common::NumberBase base); - NumbersAndOperatorsEnum m_CurrentAngleType; + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum ConvertIntegerToNumbersAndOperatorsEnum(unsigned int parameter); + static RadixType GetRadixTypeFromNumberBase(CalculatorApp::ViewModel::Common::NumberBase base); + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum m_CurrentAngleType; wchar_t m_decimalSeparator; - CalculatorDisplay m_calculatorDisplay; - CalculatorApp::EngineResourceProvider m_resourceProvider; + CalculatorApp::ViewModel::Common::CalculatorDisplay m_calculatorDisplay; + CalculatorApp::ViewModel::Common::EngineResourceProvider m_resourceProvider; CalculationManager::CalculatorManager m_standardCalculatorManager; Platform::String ^ m_expressionAutomationNameFormat; Platform::String ^ m_localizedCalculationResultAutomationFormat; @@ -336,18 +339,18 @@ namespace CalculatorApp bool m_isRtlLanguage; bool m_operandUpdated; bool m_isLastOperationHistoryLoad; - CalculatorApp::Common::BitLength m_valueBitLength; + CalculatorApp::ViewModel::Common::BitLength m_valueBitLength; Platform::String ^ m_selectedExpressionLastData; Common::DisplayExpressionToken ^ m_selectedExpressionToken; Platform::String ^ LocalizeDisplayValue(_In_ std::wstring const& displayValue); Platform::String ^ CalculateNarratorDisplayValue(_In_ std::wstring const& displayValue, _In_ Platform::String ^ localizedDisplayValue); - CalculatorApp::Common::Automation::NarratorAnnouncement ^ GetDisplayUpdatedNarratorAnnouncement(); + CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^ GetDisplayUpdatedNarratorAnnouncement(); Platform::String ^ GetCalculatorExpressionAutomationName(); Platform::String ^ GetNarratorStringReadRawNumbers(_In_ Platform::String ^ localizedDisplayValue); - CalculationManager::Command ConvertToOperatorsEnum(NumbersAndOperatorsEnum operation); + CalculationManager::Command ConvertToOperatorsEnum(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum operation); void DisableButtons(CalculationManager::CommandType selectedExpressionCommandType); Platform::String ^ m_feedbackForButtonPress; @@ -368,9 +371,9 @@ namespace CalculatorApp void SaveEditedCommand(_In_ unsigned int index, _In_ CalculationManager::Command command); - CalculatorApp::Common::ViewMode GetCalculatorMode(); + CalculatorApp::ViewModel::Common::ViewMode GetCalculatorMode(); - friend class CalculatorDisplay; + friend class CalculatorApp::ViewModel::Common::CalculatorDisplay; friend class CalculatorUnitTests::MultiWindowUnitTests; }; } diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index 90960eb8..47848538 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -15,9 +15,10 @@ #include "DataLoaders/UnitConverterDataLoader.h" using namespace CalculatorApp; -using namespace CalculatorApp::Common; -using namespace CalculatorApp::Common::Automation; using namespace CalculatorApp::ViewModel; +using namespace CalculatorApp::ViewModel::Common; +using namespace CalculatorApp::ViewModel::Common::Automation; +using namespace CalculatorApp::ViewModel::DataLoaders; using namespace concurrency; using namespace Platform; using namespace Platform::Collections; @@ -75,7 +76,7 @@ namespace StringReference SupplementaryVisibilityPropertyName(L"SupplementaryVisibility"); } -namespace CalculatorApp::ViewModel::UnitConverterResourceKeys +namespace CalculatorApp::ViewModel::DataLoaders::UnitConverterResourceKeys { StringReference ValueFromFormat(L"Format_ValueFrom"); StringReference ValueFromDecimalFormat(L"Format_ValueFrom_Decimal"); @@ -128,7 +129,7 @@ UnitConverterViewModel::UnitConverterViewModel(const shared_ptrGetRegionalSettingsAwareDecimalFormatter(); m_decimalFormatter->FractionDigits = 0; m_decimalFormatter->IsGrouped = true; - m_decimalSeparator = LocalizationSettings::GetInstance().GetDecimalSeparator(); + m_decimalSeparator = LocalizationSettings::GetInstance()->GetDecimalSeparator(); m_currencyFormatter = localizationService->GetRegionalSettingsAwareCurrencyFormatter(); m_currencyFormatter->IsGrouped = true; @@ -536,7 +537,7 @@ void UnitConverterViewModel::OnPasteCommand(Platform::Object ^ parameter) // Any converter ViewMode is fine here. auto that(this); - create_task(CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode), NumberBase::Unknown, BitLength::BitLengthUnknown)) + create_task(CopyPasteManager::GetStringToPaste(m_Mode, NavCategoryStates::GetGroupType(m_Mode), NumberBase::Unknown, BitLength::BitLengthUnknown)) .then([that](String ^ pastedString) { that->OnPaste(pastedString); }, concurrency::task_continuation_context::use_current()); } @@ -922,10 +923,10 @@ NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(const wch if (mappedValue == NumbersAndOperatorsEnum::None) { - if (LocalizationSettings::GetInstance().IsLocalizedDigit(ch)) + if (LocalizationSettings::GetInstance()->IsLocalizedDigit(ch)) { mappedValue = NumbersAndOperatorsEnum::Zero - + static_cast(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'0')); + + static_cast(ch - LocalizationSettings::GetInstance()->GetDigitSymbolFromEnUsDigit(L'0')); canSendNegate = true; } } diff --git a/src/CalcViewModel/UnitConverterViewModel.h b/src/CalcViewModel/UnitConverterViewModel.h index b48c1c3b..64c75162 100644 --- a/src/CalcViewModel/UnitConverterViewModel.h +++ b/src/CalcViewModel/UnitConverterViewModel.h @@ -35,6 +35,11 @@ namespace CalculatorApp } } + int GetModelCategoryId() + { + return GetModelCategory().id; + } + internal : const UnitConversionManager::Category& GetModelCategory() const { return m_original; @@ -70,38 +75,51 @@ namespace CalculatorApp return AccessibleName; } - internal : const UnitConversionManager::Unit& GetModelUnit() const + public: + bool IsModelUnitWhimsical() { - return m_original; + return m_original.isWhimsical; } + int ModelUnitID() + { + return m_original.id; + } + + internal: + const UnitConversionManager::Unit& GetModelUnit() const + { + return m_original; + } + private: const UnitConversionManager::Unit m_original; }; [Windows::UI::Xaml::Data::Bindable] public ref class SupplementaryResult sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged { - internal : SupplementaryResult(Platform::String ^ value, Unit ^ unit) + internal: + SupplementaryResult(Platform::String ^ value, Unit ^ unit) : m_Value(value) , m_Unit(unit) { } - bool IsWhimsical() const + public: + bool IsWhimsical() { return m_Unit->GetModelUnit().isWhimsical; } Platform::String ^ GetLocalizedAutomationName(); - public: OBSERVABLE_OBJECT(); OBSERVABLE_PROPERTY_R(Platform::String ^, Value); OBSERVABLE_PROPERTY_R(CalculatorApp::ViewModel::Unit ^, Unit); }; - interface class IActivatable + public interface class IActivatable { virtual property bool IsActive; }; @@ -143,7 +161,7 @@ namespace CalculatorApp OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Categories); - OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, Mode); + OBSERVABLE_PROPERTY_RW(CalculatorApp::ViewModel::Common::ViewMode, Mode); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, Units); OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencySymbol1); OBSERVABLE_PROPERTY_RW(Unit ^, Unit1); @@ -158,7 +176,7 @@ namespace CalculatorApp OBSERVABLE_PROPERTY_RW(Platform::String ^, Value2AutomationName); OBSERVABLE_PROPERTY_RW(Platform::String ^, Unit1AutomationName); OBSERVABLE_PROPERTY_RW(Platform::String ^, Unit2AutomationName); - OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement); + OBSERVABLE_PROPERTY_RW(CalculatorApp::ViewModel::Common::Automation::NarratorAnnouncement ^, Announcement); OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled); OBSERVABLE_PROPERTY_RW(bool, IsDropDownOpen); OBSERVABLE_PROPERTY_RW(bool, IsDropDownEnabled); @@ -167,7 +185,7 @@ namespace CalculatorApp OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencyRatioEquality); OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencyRatioEqualityAutomationName); OBSERVABLE_PROPERTY_RW(Platform::String ^, CurrencyTimestamp); - OBSERVABLE_NAMED_PROPERTY_RW(CalculatorApp::NetworkAccessBehavior, NetworkBehavior); + OBSERVABLE_NAMED_PROPERTY_RW(CalculatorApp::ViewModel::Common::NetworkAccessBehavior, NetworkBehavior); OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataLoadFailed); OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataIsWeekOld); @@ -185,7 +203,7 @@ namespace CalculatorApp if (value != nullptr) { auto currentCategory = value->GetModelCategory(); - IsCurrencyCurrentCategory = currentCategory.id == CalculatorApp::Common::NavCategory::Serialize(CalculatorApp::Common::ViewMode::Currency); + IsCurrencyCurrentCategory = currentCategory.id == CalculatorApp::ViewModel::Common::NavCategoryStates::Serialize(CalculatorApp::ViewModel::Common::ViewMode::Currency); } RaisePropertyChanged("CurrentCategory"); } @@ -217,12 +235,14 @@ namespace CalculatorApp void AnnounceConversionResult(); + void OnPaste(Platform::String ^ stringToPaste); + void RefreshCurrencyRatios(); + void OnValueActivated(IActivatable ^ control); + internal : void ResetView(); void PopulateData(); - NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate); + CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate); void DisplayPasteError(); - void OnValueActivated(IActivatable ^ control); - void OnPaste(Platform::String ^ stringToPaste); void OnCopyCommand(Platform::Object ^ parameter); void OnPasteCommand(Platform::Object ^ parameter); @@ -255,8 +275,7 @@ namespace CalculatorApp void OnCurrencyDataLoadFinished(bool didLoad); void OnCurrencyTimestampUpdated(_In_ const std::wstring& timestamp, bool isWeekOld); - void RefreshCurrencyRatios(); - void OnNetworkBehaviorChanged(_In_ CalculatorApp::NetworkAccessBehavior newBehavior); + void OnNetworkBehaviorChanged(_In_ CalculatorApp::ViewModel::Common::NetworkAccessBehavior newBehavior); const std::wstring& GetValueFromUnlocalized() const { @@ -282,7 +301,7 @@ namespace CalculatorApp void OnCategoryChanged(Platform::Object ^ unused); void OnUnitChanged(Platform::Object ^ unused); void OnSwitchActive(Platform::Object ^ unused); - UnitConversionManager::Command CommandFromButtonId(CalculatorApp::NumbersAndOperatorsEnum button); + UnitConversionManager::Command CommandFromButtonId(CalculatorApp::ViewModel::Common::NumbersAndOperatorsEnum button); void SupplementaryResultsTimerTick(Windows::System::Threading::ThreadPoolTimer ^ timer); void SupplementaryResultsTimerCancel(Windows::System::Threading::ThreadPoolTimer ^ timer); void RefreshSupplementaryResults(); @@ -449,7 +468,7 @@ namespace CalculatorApp void NetworkBehaviorChanged(_In_ int newBehavior) override { - m_viewModel->OnNetworkBehaviorChanged(static_cast(newBehavior)); + m_viewModel->OnNetworkBehaviorChanged(static_cast(newBehavior)); } private: diff --git a/src/CalcViewModel/ViewState.cpp b/src/CalcViewModel/ViewState.cpp deleted file mode 100644 index 63a5d30e..00000000 --- a/src/CalcViewModel/ViewState.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" -#include "ViewState.h" - -namespace CalculatorApp -{ - namespace ViewState - { - Platform::StringReference Snap(L"Snap"); - Platform::StringReference DockedView(L"DockedView"); - - bool IsValidViewState(Platform::String ^ viewState) - { - return viewState->Equals(ViewState::Snap) || viewState->Equals(ViewState::DockedView); - } - } -} diff --git a/src/CalcViewModel/ViewState.h b/src/CalcViewModel/ViewState.h deleted file mode 100644 index 0a103d09..00000000 --- a/src/CalcViewModel/ViewState.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -namespace CalculatorApp -{ - namespace ViewState - { - extern Platform::StringReference Snap; - extern Platform::StringReference DockedView; - - bool IsValidViewState(Platform::String ^ viewState); - } -} diff --git a/src/CalcViewModel/pch.h b/src/CalcViewModel/pch.h index da6ea470..5b188017 100644 --- a/src/CalcViewModel/pch.h +++ b/src/CalcViewModel/pch.h @@ -42,14 +42,3 @@ #include "winrt/Windows.UI.Xaml.h" #include "winrt/Windows.Foundation.Metadata.h" #include "winrt/Windows.Management.Policies.h" - -// The following namespaces exist as a convenience to resolve -// ambiguity for Windows types in the Windows::UI::Xaml::Automation::Peers -// namespace that only exist on RS3. -// Once the app switches to min version RS3, the namespaces can be removed. -// TODO - MSFT 12735088 -namespace StandardPeers = Windows::UI::Xaml::Automation::Peers; -namespace CalculatorApp::Common::Automation -{ -} -namespace CustomPeers = CalculatorApp::Common::Automation; diff --git a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj new file mode 100644 index 00000000..7aef42f5 --- /dev/null +++ b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj @@ -0,0 +1,414 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {cc9b4fa7-d746-4f52-9401-0ad1b4d6b16d} + StaticLibrary + CalcViewModelCopyForUT + en-US + 14.0 + true + Windows Store + 10.0.22621.0 + 10.0.19041.0 + 10.0 + + + + StaticLibrary + true + v143 + + + StaticLibrary + true + v143 + + + StaticLibrary + true + v143 + + + StaticLibrary + true + v143 + + + StaticLibrary + false + true + v143 + + + StaticLibrary + false + true + v143 + + + StaticLibrary + false + true + v143 + + + StaticLibrary + false + true + v143 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + true + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir);$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + Use + true + true + $(SolutionDir)..\src\;$(SolutionDir)CalcViewModel\;%(AdditionalIncludeDirectories) + 4453 + /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions) + Level4 + true + + + Console + false + false + + + /ignore:4264 %(AdditionalOptions) + + + + + /DSEND_DIAGNOSTICS %(AdditionalOptions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + Create + Create + + + + + + + {311e866d-8b93-4609-a691-265941fee101} + + + {e727a92b-f149-492c-8117-c039a298719b} + + + {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed} + + + + + /DUSE_MOCK_DATA %(AdditionalOptions) + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters new file mode 100644 index 00000000..19ca2cee --- /dev/null +++ b/src/CalcViewModelCopyForUT/CalcViewModelCopyForUT.vcxproj.filters @@ -0,0 +1,213 @@ + + + + + {2c2762e9-7673-4c4e-bf31-9513125dfc00} + + + {8f48b19f-14df-421f-bcc6-ef908f9dcff0} + + + {6811c769-d698-4add-b477-794316d39c66} + + + {da163ad4-d001-45eb-b4b3-6e9e17d22077} + + + + + Common + + + Common\Automation + + + Common\Automation + + + + + + + + + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + GraphingCalculator + + + GraphingCalculator + + + GraphingCalculator + + + + + + Common + + + Common\Automation + + + Common\Automation + + + + + + + + + + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + Common + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + DataLoaders + + + GraphingCalculator + + + GraphingCalculator + + + GraphingCalculator + + + GraphingCalculator + + + + Common + + + + + DataLoaders + + + \ No newline at end of file diff --git a/src/Calculator.sln b/src/Calculator.sln index 09fc81fd..9458f929 100644 --- a/src/Calculator.sln +++ b/src/Calculator.sln @@ -1,19 +1,19 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29009.5 -MinimumVisualStudioVersion = 10.0.40219.1 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.0.0 +MinimumVisualStudioVersion = 17.0.0.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3A5DF651-B8A1-45CA-9135-964A6FC7F5D1}" ProjectSection(SolutionItems) = preProject ..\.clang-format = ..\.clang-format nuget.config = nuget.config EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Calculator", "Calculator\Calculator.vcxproj", "{9447424A-0E05-4911-BEB8-E0354405F39A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator", "Calculator\Calculator.csproj", "{3B773403-B0D6-4F9A-948E-512A7A5FB315}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcManager", "CalcManager\CalcManager.vcxproj", "{311E866D-8B93-4609-A691-265941FEE101}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModel", "CalcViewModel\CalcViewModel.vcxproj", "{90E9761D-9262-4773-942D-CAEAE75D7140}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModel", "CalcViewModel\CalcViewModel.vcxproj", "{812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorUnitTests", "CalculatorUnitTests\CalculatorUnitTests.vcxproj", "{D3BAED2C-4B07-4E1D-8807-9D6499450349}" EndProject @@ -27,6 +27,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GraphControl", "GraphContro EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TraceLogging", "TraceLogging\TraceLogging.vcxproj", "{FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModelCopyForUT", "CalcViewModelCopyForUT\CalcViewModelCopyForUT.vcxproj", "{CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -39,30 +41,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.ActiveCfg = Debug|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.Build.0 = Debug|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM.Deploy.0 = Debug|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM64.Build.0 = Debug|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x64.ActiveCfg = Debug|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x64.Build.0 = Debug|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x64.Deploy.0 = Debug|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x86.ActiveCfg = Debug|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x86.Build.0 = Debug|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Debug|x86.Deploy.0 = Debug|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM.ActiveCfg = Release|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM.Build.0 = Release|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM.Deploy.0 = Release|ARM - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM64.ActiveCfg = Release|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM64.Build.0 = Release|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|ARM64.Deploy.0 = Release|ARM64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x64.ActiveCfg = Release|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x64.Build.0 = Release|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x64.Deploy.0 = Release|x64 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.ActiveCfg = Release|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.Build.0 = Release|Win32 - {9447424A-0E05-4911-BEB8-E0354405F39A}.Release|x86.Deploy.0 = Release|Win32 {311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.ActiveCfg = Debug|ARM {311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM.Build.0 = Debug|ARM {311E866D-8B93-4609-A691-265941FEE101}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -79,22 +57,22 @@ Global {311E866D-8B93-4609-A691-265941FEE101}.Release|x64.Build.0 = Release|x64 {311E866D-8B93-4609-A691-265941FEE101}.Release|x86.ActiveCfg = Release|Win32 {311E866D-8B93-4609-A691-265941FEE101}.Release|x86.Build.0 = Release|Win32 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM.ActiveCfg = Debug|ARM - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM.Build.0 = Debug|ARM - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|ARM64.Build.0 = Debug|ARM64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x64.ActiveCfg = Debug|x64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x64.Build.0 = Debug|x64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x86.ActiveCfg = Debug|Win32 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Debug|x86.Build.0 = Debug|Win32 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM.ActiveCfg = Release|ARM - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM.Build.0 = Release|ARM - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM64.ActiveCfg = Release|ARM64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|ARM64.Build.0 = Release|ARM64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x64.ActiveCfg = Release|x64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x64.Build.0 = Release|x64 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x86.ActiveCfg = Release|Win32 - {90E9761D-9262-4773-942D-CAEAE75D7140}.Release|x86.Build.0 = Release|Win32 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|ARM.ActiveCfg = Debug|ARM + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|ARM.Build.0 = Debug|ARM + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|ARM64.Build.0 = Debug|ARM64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|x64.ActiveCfg = Debug|x64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|x64.Build.0 = Debug|x64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|x86.ActiveCfg = Debug|Win32 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Debug|x86.Build.0 = Debug|Win32 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|ARM.ActiveCfg = Release|ARM + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|ARM.Build.0 = Release|ARM + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|ARM64.ActiveCfg = Release|ARM64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|ARM64.Build.0 = Release|ARM64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|x64.ActiveCfg = Release|x64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|x64.Build.0 = Release|x64 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|x86.ActiveCfg = Release|Win32 + {812D1A7B-B8AC-49E4-8E6D-AF5D59500D56}.Release|x86.Build.0 = Release|Win32 {D3BAED2C-4B07-4E1D-8807-9D6499450349}.Debug|ARM.ActiveCfg = Debug|ARM {D3BAED2C-4B07-4E1D-8807-9D6499450349}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D3BAED2C-4B07-4E1D-8807-9D6499450349}.Debug|x64.ActiveCfg = Debug|x64 @@ -191,13 +169,48 @@ Global {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x64.Build.0 = Release|x64 {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x86.ActiveCfg = Release|Win32 {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x86.Build.0 = Release|Win32 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM.ActiveCfg = Debug|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM.Build.0 = Debug|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM.Deploy.0 = Debug|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM64.Build.0 = Debug|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x64.ActiveCfg = Debug|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x64.Build.0 = Debug|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x64.Deploy.0 = Debug|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x86.ActiveCfg = Debug|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x86.Build.0 = Debug|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Debug|x86.Deploy.0 = Debug|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM.ActiveCfg = Release|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM.Build.0 = Release|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM.Deploy.0 = Release|ARM + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM64.ActiveCfg = Release|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM64.Build.0 = Release|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|ARM64.Deploy.0 = Release|ARM64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x64.ActiveCfg = Release|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x64.Build.0 = Release|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x64.Deploy.0 = Release|x64 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x86.ActiveCfg = Release|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x86.Build.0 = Release|x86 + {3B773403-B0D6-4F9A-948E-512A7A5FB315}.Release|x86.Deploy.0 = Release|x86 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|ARM.ActiveCfg = Debug|ARM + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|ARM.Build.0 = Debug|ARM + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|x64.ActiveCfg = Debug|x64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|x64.Build.0 = Debug|x64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|x86.ActiveCfg = Debug|Win32 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Debug|x86.Build.0 = Debug|Win32 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|ARM.ActiveCfg = Release|ARM + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|ARM.Build.0 = Release|ARM + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|ARM64.ActiveCfg = Release|ARM64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|x64.ActiveCfg = Release|x64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|x64.Build.0 = Release|x64 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|x86.ActiveCfg = Release|Win32 + {CC9B4FA7-D746-4F52-9401-0AD1B4D6B16D}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {311E866D-8B93-4609-A691-265941FEE101} = {3A5DF651-B8A1-45CA-9135-964A6FC7F5D1} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0EA53F83-5FA6-46A1-A290-A3C6962D2CAC} EndGlobalSection diff --git a/src/Calculator/AboutFlyout.xaml b/src/Calculator/AboutFlyout.xaml deleted file mode 100644 index b83dfd83..00000000 --- a/src/Calculator/AboutFlyout.xaml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -