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).
-[](https://dev.azure.com/ms/calculator/_build/latest?definitionId=57&branchName=master)
+[](https://dev.azure.com/ms/calculator/_build/latest?definitionId=57&branchName=main)

@@ -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.

- 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 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Calculator/AboutFlyout.xaml.cpp b/src/Calculator/AboutFlyout.xaml.cpp
deleted file mode 100644
index c89c7df5..00000000
--- a/src/Calculator/AboutFlyout.xaml.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-#include "pch.h"
-#include "AboutFlyout.xaml.h"
-#include "CalcViewModel/Common/AppResourceProvider.h"
-#include "CalcViewModel/Common/LocalizationService.h"
-#include "CalcViewModel/Common/LocalizationStringUtil.h"
-#include "CalcViewModel/Common/TraceLogger.h"
-
-using namespace std;
-using namespace CalculatorApp;
-using namespace CalculatorApp::Common;
-using namespace Platform;
-using namespace Windows::ApplicationModel;
-using namespace Windows::Foundation;
-using namespace Windows::System;
-using namespace Windows::UI::Xaml;
-using namespace Windows::UI::Xaml::Controls;
-using namespace Windows::UI::Xaml::Controls::Primitives;
-using namespace Windows::UI::Xaml::Data;
-
-#ifndef BUILD_YEAR
-#define BUILD_YEAR 2021
-#endif
-
-AboutFlyout::AboutFlyout()
-{
- auto locService = LocalizationService::GetInstance();
- auto resourceLoader = AppResourceProvider::GetInstance();
-
- InitializeComponent();
-
- Language = locService->GetLanguage();
-
- this->SetVersionString();
-
- Header->Text = resourceLoader->GetResourceString("AboutButton/Content");
-
- auto copyrightText =
- LocalizationStringUtil::GetLocalizedString(resourceLoader->GetResourceString("AboutControlCopyright"), StringReference(to_wstring(BUILD_YEAR).c_str()));
- AboutControlCopyrightRun->Text = copyrightText;
-
- InitializeContributeTextBlock();
-}
-
-void AboutFlyout::FeedbackButton_Click(_In_ Object ^ sender, _In_ RoutedEventArgs ^ e)
-{
- PackageVersion version = Package::Current->Id->Version;
- String ^ versionNumber = ref new String(L"Version ");
- versionNumber = versionNumber + version.Major + "." + version.Minor + "." + version.Build + "." + version.Revision;
- Launcher::LaunchUriAsync(ref new Uri("windows-feedback:?contextid=130&metadata=%7B%22Metadata%22:[%7B%22AppBuild%22:%22" + versionNumber + "%22%7D]%7D"));
-}
-
-void AboutFlyout::SetVersionString()
-{
- PackageVersion version = Package::Current->Id->Version;
- String ^ appName = AppResourceProvider::GetInstance()->GetResourceString(L"AppName");
- AboutFlyoutVersion->Text = appName + L" " + version.Major + L"." + version.Minor + L"." + version.Build + L"." + version.Revision;
-}
-
-void AboutFlyout::SetDefaultFocus()
-{
- AboutFlyoutEULA->Focus(::FocusState::Programmatic);
-}
-
-void AboutFlyout::InitializeContributeTextBlock()
-{
- auto resProvider = AppResourceProvider::GetInstance();
- std::wstring contributeHyperlinkText = resProvider->GetResourceString(L"AboutFlyoutContribute")->Data();
-
- // The resource string has the 'GitHub' hyperlink wrapped with '%HL%'.
- // Break the string and assign pieces appropriately.
- static const std::wstring delimiter{ L"%HL%" };
- static const size_t delimiterLength{ delimiter.length() };
-
- // Find the delimiters.
- size_t firstSplitPosition = contributeHyperlinkText.find(delimiter, 0);
- assert(firstSplitPosition != std::wstring::npos);
- size_t secondSplitPosition = contributeHyperlinkText.find(delimiter, firstSplitPosition + 1);
- assert(secondSplitPosition != std::wstring::npos);
- size_t hyperlinkTextLength = secondSplitPosition - (firstSplitPosition + delimiterLength);
-
- // Assign pieces.
- auto contributeTextBeforeHyperlink = ref new String(contributeHyperlinkText.substr(0, firstSplitPosition).c_str());
- auto contributeTextLink = ref new String(contributeHyperlinkText.substr(firstSplitPosition + delimiterLength, hyperlinkTextLength).c_str());
- auto contributeTextAfterHyperlink = ref new String(contributeHyperlinkText.substr(secondSplitPosition + delimiterLength).c_str());
-
- ContributeRunBeforeLink->Text = contributeTextBeforeHyperlink;
- ContributeRunLink->Text = contributeTextLink;
- ContributeRunAfterLink->Text = contributeTextAfterHyperlink;
-}
diff --git a/src/Calculator/AboutFlyout.xaml.h b/src/Calculator/AboutFlyout.xaml.h
deleted file mode 100644
index f4e47a36..00000000
--- a/src/Calculator/AboutFlyout.xaml.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-#pragma once
-
-#include "AboutFlyout.g.h"
-
-namespace CalculatorApp
-{
-public
- ref class AboutFlyout sealed
- {
- public:
- AboutFlyout();
-
- void SetDefaultFocus();
-
- private:
- void FeedbackButton_Click(_In_ Platform::Object ^ sender, _In_ Windows::UI::Xaml::RoutedEventArgs ^ e);
- void SetVersionString();
- void InitializeContributeTextBlock();
- };
-} /* namespace CalculatorApp */
diff --git a/src/Calculator/App.xaml b/src/Calculator/App.xaml
index 4a0cca57..e2a61fc1 100644
--- a/src/Calculator/App.xaml
+++ b/src/Calculator/App.xaml
@@ -3,15 +3,48 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="using:CalculatorApp.Controls"
xmlns:common="using:CalculatorApp.Common"
- xmlns:local="using:CalculatorApp">
+ xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)"
+ xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
+ xmlns:converters="using:CalculatorApp.Converters"
+ xmlns:local="using:CalculatorApp"
+ xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
+ xmlns:primitives="using:Microsoft.UI.Xaml.Controls.Primitives"
+ xmlns:utils="using:CalculatorApp.Utils">
+
+
+
+
+
+
+ 0
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
0,0,0,0
0
#FF000000
@@ -19,7 +52,6 @@
#FF858585
-
@@ -84,9 +116,48 @@
-
+
+
+
+
+
+ #FFFFFF
+
+
+
+
+
+
+
+
+
+ #000000
+
+
+
+
+
+ 0
0,0,0,0
0
#FFF2F2F2
@@ -94,7 +165,6 @@
#FF858585
-
@@ -163,14 +233,52 @@
-
+
+
+
+
+
+ #FFFFFF
+
+
+
+
+
+
+
+
+
+ #000000
+
+
+
+
+
+ 1
0,1,0,0
2
-
@@ -198,7 +306,25 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -206,36 +332,40 @@
500
320
- ms-appx:///Assets/CalcMDL2.ttf#Calculator MDL2 Assets
+ ms-appx:///Assets/CalculatorIcons.ttf#Calculator Fluent Icons
256
0,1,0,0
- 15
- SemiBold
+ 14
+ Normal
- 64
+ 70
24
24
16
- 64
+ 70
16
20
10
- 38
+ 44
12
16
- 8
+ 12
12
- 15
+ 14
24
-
- 40
- 40
+ 14
+ SemiBold
+
+ 48
+ 48
+
+ 32
34
38
48
@@ -247,25 +377,31 @@
12
14
+ 12
16
+
+
-
@@ -414,59 +584,98 @@
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
+
+ ContentTransitions="{TemplateBinding ContentTransitions}">
+
+
+
+
+
+ Glyph=""/>
+ Glyph=""/>
+
+
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
-
-
+
+
+
+
+
diff --git a/src/Calculator/App.xaml.cpp b/src/Calculator/App.xaml.cpp
deleted file mode 100644
index 938b5d23..00000000
--- a/src/Calculator/App.xaml.cpp
+++ /dev/null
@@ -1,439 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-//
-// App.xaml.cpp
-// Implementation of the App class.
-//
-
-#include "pch.h"
-#include "App.xaml.h"
-#include "CalcViewModel/Common/TraceLogger.h"
-#include "CalcViewModel/Common/Automation/NarratorNotifier.h"
-#include "CalcViewModel/Common/AppResourceProvider.h"
-#include "CalcViewModel/Common/LocalizationSettings.h"
-#include "Views/MainPage.xaml.h"
-
-using namespace CalculatorApp;
-using namespace CalculatorApp::Common;
-using namespace CalculatorApp::Common::Automation;
-
-using namespace Concurrency;
-using namespace Microsoft::WRL;
-using namespace Platform;
-using namespace Windows::ApplicationModel;
-using namespace Windows::ApplicationModel::Activation;
-using namespace Windows::ApplicationModel::Core;
-using namespace Windows::ApplicationModel::Resources;
-using namespace Windows::Foundation;
-using namespace Windows::Foundation::Collections;
-using namespace Windows::Storage;
-using namespace Windows::System;
-using namespace Windows::UI::Core;
-using namespace Windows::UI::Popups;
-using namespace Windows::UI::StartScreen;
-using namespace Windows::UI::ViewManagement;
-using namespace Windows::UI::Xaml;
-using namespace Windows::UI::Xaml::Controls;
-using namespace Windows::UI::Xaml::Controls::Primitives;
-using namespace Windows::UI::Xaml::Data;
-using namespace Windows::UI::Xaml::Input;
-using namespace Windows::UI::Xaml::Interop;
-using namespace Windows::UI::Xaml::Media;
-using namespace Windows::UI::Xaml::Media::Animation;
-using namespace Windows::UI::Xaml::Navigation;
-using namespace Windows::ApplicationModel::Activation;
-
-namespace CalculatorApp
-{
- namespace ApplicationResourceKeys
- {
- StringReference AppMinWindowHeight(L"AppMinWindowHeight");
- StringReference AppMinWindowWidth(L"AppMinWindowWidth");
- }
-}
-
-///
-/// Initializes the singleton application object. This is the first line of authored code
-/// executed, and as such is the logical equivalent of main() or WinMain().
-///
-App::App()
-{
- InitializeComponent();
-
- m_preLaunched = false;
-
- RegisterDependencyProperties();
-
- // TODO: MSFT 14645325: Set this directly from XAML.
- // Currently this is bugged so the property is only respected from code-behind.
- this->HighContrastAdjustment = ApplicationHighContrastAdjustment::None;
-
- this->Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
-
-#if _DEBUG
- this->DebugSettings->IsBindingTracingEnabled = true;
- this->DebugSettings->BindingFailed += ref new BindingFailedEventHandler([](_In_ Object ^ /*sender*/, _In_ BindingFailedEventArgs ^ e) {
- if (IsDebuggerPresent())
- {
- ::Platform::String ^ errorMessage = e->Message;
- __debugbreak();
- }
- });
-#endif
-}
-
-void App::AddWindowToMap(_In_ WindowFrameService ^ frameService)
-{
- reader_writer_lock::scoped_lock lock(m_windowsMapLock);
- m_secondaryWindows[frameService->GetViewId()] = frameService;
- TraceLogger::GetInstance()->UpdateWindowCount(m_secondaryWindows.size());
-}
-
-WindowFrameService ^ App::GetWindowFromMap(int viewId)
-{
- reader_writer_lock::scoped_lock_read lock(m_windowsMapLock);
- auto windowMapEntry = m_secondaryWindows.find(viewId);
- if (windowMapEntry != m_secondaryWindows.end())
- {
- return windowMapEntry->second;
- }
- return nullptr;
-}
-
-void App::RemoveWindowFromMap(int viewId)
-{
- reader_writer_lock::scoped_lock lock(m_windowsMapLock);
- auto iter = m_secondaryWindows.find(viewId);
- assert(iter != m_secondaryWindows.end() && "Window does not exist in the list");
- m_secondaryWindows.erase(viewId);
-}
-
-void App::RemoveWindow(_In_ WindowFrameService ^ frameService)
-{
- // Shell does not allow killing the main window.
- if (m_mainViewId != frameService->GetViewId())
- {
- HandleViewReleaseAndRemoveWindowFromMap(frameService);
- }
-}
-
-task App::HandleViewReleaseAndRemoveWindowFromMap(_In_ WindowFrameService ^ frameService)
-{
- WeakReference weak(this);
-
- // Unregister the event handler of the Main Page
- auto frame = safe_cast(Window::Current->Content);
- auto mainPage = safe_cast(frame->Content);
- mainPage->UnregisterEventHandlers();
-
- return frameService->HandleViewRelease().then(
- [weak, frameService]() {
- auto that = weak.Resolve();
- that->RemoveWindowFromMap(frameService->GetViewId());
- },
- task_continuation_context::use_arbitrary());
-}
-
-#pragma optimize("", off) // Turn off optimizations to work around coroutine optimization bug
-task App::SetupJumpList()
-{
- try
- {
- auto calculatorOptions = NavCategoryGroup::CreateCalculatorCategory();
-
- auto jumpList = co_await JumpList::LoadCurrentAsync();
- jumpList->SystemGroupKind = JumpListSystemGroupKind::None;
- jumpList->Items->Clear();
-
- for (NavCategory ^ option : calculatorOptions->Categories)
- {
- if (!option->IsEnabled)
- {
- continue;
- }
- ViewMode mode = option->Mode;
- auto item = JumpListItem::CreateWithArguments(((int)mode).ToString(), L"ms-resource:///Resources/" + NavCategory::GetNameResourceKey(mode));
- item->Description = L"ms-resource:///Resources/" + NavCategory::GetNameResourceKey(mode);
- item->Logo = ref new Uri("ms-appx:///Assets/" + mode.ToString() + ".png");
-
- jumpList->Items->Append(item);
- }
-
- co_await jumpList->SaveAsync();
- }
- catch (...)
- {
- }
-};
-#pragma optimize("", on)
-
-void App::RemoveSecondaryWindow(_In_ WindowFrameService ^ frameService)
-{
- // Shell does not allow killing the main window.
- if (m_mainViewId != frameService->GetViewId())
- {
- RemoveWindowFromMap(frameService->GetViewId());
- }
-}
-
-Frame ^ App::CreateFrame()
-{
- auto frame = ref new Frame();
- frame->FlowDirection = LocalizationService::GetInstance()->GetFlowDirection();
-
- return frame;
-}
-
-///
-/// Invoked when the application is launched normally by the end user. Other entry points
-/// will be used when the application is launched to open a specific file, to display
-/// search results, and so forth.
-///
-/// Details about the launch request and process.
-void App::OnLaunched(LaunchActivatedEventArgs ^ args)
-{
- if (args->PrelaunchActivated)
- {
- // If the app got pre-launch activated, then save that state in a flag
- m_preLaunched = true;
- }
- NavCategory::InitializeCategoryManifest(args->User);
- OnAppLaunch(args, args->Arguments);
-}
-
-void App::OnAppLaunch(IActivatedEventArgs ^ args, String ^ argument)
-{
- // Uncomment the following lines to display frame-rate and per-frame CPU usage info.
- //#if _DEBUG
- // if (IsDebuggerPresent())
- // {
- // DebugSettings->EnableFrameRateCounter = true;
- // }
- //#endif
-
- args->SplashScreen->Dismissed += ref new TypedEventHandler(this, &App::DismissedEventHandler);
-
- auto rootFrame = dynamic_cast(Window::Current->Content);
- WeakReference weak(this);
-
- float minWindowWidth = static_cast(static_cast(this->Resources->Lookup(ApplicationResourceKeys::AppMinWindowWidth)));
- float minWindowHeight = static_cast(static_cast(this->Resources->Lookup(ApplicationResourceKeys::AppMinWindowHeight)));
- Size minWindowSize = SizeHelper::FromDimensions(minWindowWidth, minWindowHeight);
-
- ApplicationView ^ appView = ApplicationView::GetForCurrentView();
- ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
- // For very first launch, set the size of the calc as size of the default standard mode
- if (!localSettings->Values->HasKey(L"VeryFirstLaunch"))
- {
- localSettings->Values->Insert(ref new String(L"VeryFirstLaunch"), false);
- appView->SetPreferredMinSize(minWindowSize);
- appView->TryResizeView(minWindowSize);
- }
- else
- {
- appView->PreferredLaunchWindowingMode = ApplicationViewWindowingMode::Auto;
- }
-
- // Do not repeat app initialization when the Window already has content,
- // just ensure that the window is active
- if (rootFrame == nullptr)
- {
- if (!Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) // PC Family
- {
- // Disable the system view activation policy during the first launch of the app
- // only for PC family devices and not for phone family devices
- try
- {
- ApplicationViewSwitcher::DisableSystemViewActivationPolicy();
- }
- catch (Exception ^ e)
- {
- // Log that DisableSystemViewActionPolicy didn't work
- }
- }
-
- // Create a Frame to act as the navigation context
- rootFrame = App::CreateFrame();
-
- // When the navigation stack isn't restored navigate to the first page,
- // configuring the new page by passing required information as a navigation
- // parameter
- if (!rootFrame->Navigate(MainPage::typeid, argument))
- {
- // We couldn't navigate to the main page, kill the app so we have a good
- // stack to debug
- throw std::bad_exception();
- }
-
- SetMinWindowSizeAndActivate(rootFrame, minWindowSize);
- m_mainViewId = ApplicationView::GetForCurrentView()->Id;
- AddWindowToMap(WindowFrameService::CreateNewWindowFrameService(rootFrame, false, weak));
- }
- else
- {
- // For first launch, LaunchStart is logged in constructor, this is for subsequent launches.
-
- // !Phone check is required because even in continuum mode user interaction mode is Mouse not Touch
- if ((UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Mouse)
- && (!Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")))
- {
- // If the pre-launch hasn't happened then allow for the new window/view creation
- if (!m_preLaunched)
- {
- auto newCoreAppView = CoreApplication::CreateNewView();
- newCoreAppView->Dispatcher->RunAsync(
- CoreDispatcherPriority::Normal, ref new DispatchedHandler([args, argument, minWindowSize, weak]() {
- auto that = weak.Resolve();
- if (that != nullptr)
- {
- auto rootFrame = App::CreateFrame();
- SetMinWindowSizeAndActivate(rootFrame, minWindowSize);
-
- if (!rootFrame->Navigate(MainPage::typeid, argument))
- {
- // We couldn't navigate to the main page, kill the app so we have a good
- // stack to debug
- throw std::bad_exception();
- }
-
- auto frameService = WindowFrameService::CreateNewWindowFrameService(rootFrame, true, weak);
- that->AddWindowToMap(frameService);
-
- auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher;
- auto safeFrameServiceCreation = std::make_shared(frameService, that);
- int newWindowId = ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread());
-
- ActivationViewSwitcher ^ activationViewSwitcher;
- auto activateEventArgs = dynamic_cast(args);
- if (activateEventArgs != nullptr)
- {
- activationViewSwitcher = activateEventArgs->ViewSwitcher;
- }
-
- if (activationViewSwitcher != nullptr)
- {
- activationViewSwitcher->ShowAsStandaloneAsync(newWindowId, ViewSizePreference::Default);
- safeFrameServiceCreation->SetOperationSuccess(true);
- }
- else
- {
- auto activatedEventArgs = dynamic_cast(args);
- if ((activatedEventArgs != nullptr) && (activatedEventArgs->CurrentlyShownApplicationViewId != 0))
- {
- create_task(ApplicationViewSwitcher::TryShowAsStandaloneAsync(
- frameService->GetViewId(),
- ViewSizePreference::Default,
- activatedEventArgs->CurrentlyShownApplicationViewId,
- ViewSizePreference::Default))
- .then(
- [safeFrameServiceCreation](bool viewShown) {
- // SafeFrameServiceCreation is used to automatically remove the frame
- // from the list of frames if something goes bad.
- safeFrameServiceCreation->SetOperationSuccess(viewShown);
- },
- task_continuation_context::use_current());
- }
- }
- }
- }));
- }
- else
- {
- ActivationViewSwitcher ^ activationViewSwitcher;
- auto activateEventArgs = dynamic_cast(args);
- if (activateEventArgs != nullptr)
- {
- activationViewSwitcher = activateEventArgs->ViewSwitcher;
- }
-
- if (activationViewSwitcher != nullptr)
- {
- activationViewSwitcher->ShowAsStandaloneAsync(
- ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()), ViewSizePreference::Default);
- }
- else
- {
- TraceLogger::GetInstance()->LogError(ViewMode::None, L"App::OnAppLaunch", L"Null_ActivationViewSwitcher");
- }
- }
- // Set the preLaunched flag to false
- m_preLaunched = false;
- }
- else // for touch devices
- {
- if (rootFrame->Content == nullptr)
- {
- // When the navigation stack isn't restored navigate to the first page,
- // configuring the new page by passing required information as a navigation
- // parameter
- if (!rootFrame->Navigate(MainPage::typeid, argument))
- {
- // We couldn't navigate to the main page,
- // kill the app so we have a good stack to debug
- throw std::bad_exception();
- }
- }
- if (ApplicationView::GetForCurrentView()->ViewMode != ApplicationViewMode::CompactOverlay)
- {
- if (!Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
- {
- // for tablet mode: since system view activation policy is disabled so do ShowAsStandaloneAsync if activationViewSwitcher exists in
- // activationArgs
- ActivationViewSwitcher ^ activationViewSwitcher;
- auto activateEventArgs = dynamic_cast(args);
- if (activateEventArgs != nullptr)
- {
- activationViewSwitcher = activateEventArgs->ViewSwitcher;
- }
- if (activationViewSwitcher != nullptr)
- {
- auto viewId = safe_cast(args)->CurrentlyShownApplicationViewId;
- if (viewId != 0)
- {
- activationViewSwitcher->ShowAsStandaloneAsync(viewId);
- }
- }
- }
- // Ensure the current window is active
- Window::Current->Activate();
- }
- }
- }
-}
-
-void App::SetMinWindowSizeAndActivate(Frame ^ rootFrame, Size minWindowSize)
-{
- // SetPreferredMinSize should always be called before Window::Activate
- ApplicationView ^ appView = ApplicationView::GetForCurrentView();
- appView->SetPreferredMinSize(minWindowSize);
-
- // Place the frame in the current Window
- Window::Current->Content = rootFrame;
- Window::Current->Activate();
-}
-
-void App::RegisterDependencyProperties()
-{
- NarratorNotifier::RegisterDependencyProperties();
-}
-
-void App::OnActivated(IActivatedEventArgs ^ args)
-{
- if (args->Kind == ActivationKind::Protocol)
- {
- // We currently don't pass the uri as an argument,
- // and handle any protocol launch as a normal app launch.
- OnAppLaunch(args, nullptr);
- }
-}
-
-void CalculatorApp::App::OnSuspending(Object ^ sender, SuspendingEventArgs ^ args)
-{
- TraceLogger::GetInstance()->LogButtonUsage();
-}
-
-void App::DismissedEventHandler(SplashScreen ^ sender, Object ^ e)
-{
- SetupJumpList();
-}
diff --git a/src/Calculator/App.xaml.cs b/src/Calculator/App.xaml.cs
new file mode 100644
index 00000000..84d75e10
--- /dev/null
+++ b/src/Calculator/App.xaml.cs
@@ -0,0 +1,512 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+//
+// App.xaml.h
+// Declaration of the App class.
+//
+
+using CalculatorApp.ViewModel.Common;
+using CalculatorApp.ViewModel.Common.Automation;
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.ApplicationModel.Core;
+using Windows.Foundation;
+using Windows.Storage;
+using Windows.UI.Core;
+using Windows.UI.StartScreen;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace CalculatorApp
+{
+ namespace ApplicationResourceKeys
+ {
+ public static class Globals
+ {
+ public static readonly string AppMinWindowHeight = "AppMinWindowHeight";
+ public static readonly string AppMinWindowWidth = "AppMinWindowWidth";
+ }
+ }
+
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ public sealed partial class App
+ {
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ InitializeComponent();
+
+ m_preLaunched = false;
+
+ RegisterDependencyProperties();
+
+ // TODO: MSFT 14645325: Set this directly from XAML.
+ // Currently this is bugged so the property is only respected from code-behind.
+ HighContrastAdjustment = ApplicationHighContrastAdjustment.None;
+
+ Suspending += OnSuspending;
+
+#if DEBUG
+ DebugSettings.IsBindingTracingEnabled = true;
+ DebugSettings.BindingFailed += (sender, args) =>
+ {
+ if (Debugger.IsAttached)
+ {
+ string errorMessage = args.Message;
+ Debugger.Break();
+ }
+ };
+#endif
+ }
+
+ ///
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used when the application is launched to open a specific file, to display
+ /// search results, and so forth.
+ ///
+ /// Details about the launch request and process.
+ protected override void OnLaunched(LaunchActivatedEventArgs args)
+ {
+ if (args.PrelaunchActivated)
+ {
+ // If the app got pre-launch activated, then save that state in a flag
+ m_preLaunched = true;
+ }
+
+ NavCategoryStates.SetCurrentUser(args.User.NonRoamableId);
+
+ // It takes time to check GraphingMode at the 1st time. So, do it in a background thread
+ Task.Run(() => NavCategoryStates.IsViewModeEnabled(ViewMode.Graphing));
+
+ OnAppLaunch(args, args.Arguments);
+ }
+
+ protected override void OnActivated(IActivatedEventArgs args)
+ {
+ if (args.Kind == ActivationKind.Protocol)
+ {
+ // We currently don't pass the uri as an argument,
+ // and handle any protocol launch as a normal app launch.
+ OnAppLaunch(args, null);
+ }
+ }
+
+ internal void RemoveWindow(WindowFrameService frameService)
+ {
+ // Shell does not allow killing the main window.
+ if (m_mainViewId != frameService.GetViewId())
+ {
+ _ = HandleViewReleaseAndRemoveWindowFromMap(frameService);
+ }
+ }
+
+ internal void RemoveSecondaryWindow(WindowFrameService frameService)
+ {
+ // Shell does not allow killing the main window.
+ if (m_mainViewId != frameService.GetViewId())
+ {
+ RemoveWindowFromMap(frameService.GetViewId());
+ }
+ }
+
+ private static Frame CreateFrame()
+ {
+ var frame = new Frame
+ {
+ FlowDirection = LocalizationService.GetInstance().GetFlowDirection()
+ };
+ return frame;
+ }
+
+ private static void SetMinWindowSizeAndThemeAndActivate(Frame rootFrame, Size minWindowSize)
+ {
+ // SetPreferredMinSize should always be called before Window.Activate
+ ApplicationView appView = ApplicationView.GetForCurrentView();
+ appView.SetPreferredMinSize(minWindowSize);
+
+ // Place the frame in the current Window
+ Window.Current.Content = rootFrame;
+ CalculatorApp.Utils.ThemeHelper.InitializeAppTheme();
+ Window.Current.Activate();
+ }
+
+ private void OnAppLaunch(IActivatedEventArgs args, string argument)
+ {
+ // Uncomment the following lines to display frame-rate and per-frame CPU usage info.
+ //#if _DEBUG
+ // if (IsDebuggerPresent())
+ // {
+ // DebugSettings->EnableFrameRateCounter = true;
+ // }
+ //#endif
+
+ args.SplashScreen.Dismissed += DismissedEventHandler;
+
+ var rootFrame = (Window.Current.Content as Frame);
+ WeakReference weak = new WeakReference(this);
+
+ float minWindowWidth = (float)((double)Resources[ApplicationResourceKeys.Globals.AppMinWindowWidth]);
+ float minWindowHeight = (float)((double)Resources[ApplicationResourceKeys.Globals.AppMinWindowHeight]);
+ Size minWindowSize = SizeHelper.FromDimensions(minWindowWidth, minWindowHeight);
+
+ ApplicationView appView = ApplicationView.GetForCurrentView();
+ ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
+ // For very first launch, set the size of the calc as size of the default standard mode
+ if (!localSettings.Values.ContainsKey("VeryFirstLaunch"))
+ {
+ localSettings.Values["VeryFirstLaunch"] = false;
+ appView.SetPreferredMinSize(minWindowSize);
+ appView.TryResizeView(minWindowSize);
+ }
+ else
+ {
+ ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.Auto;
+ }
+
+ // Do not repeat app initialization when the Window already has content,
+ // just ensure that the window is active
+ if (rootFrame == null)
+ {
+ if (!Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) // PC Family
+ {
+ // Disable the system view activation policy during the first launch of the app
+ // only for PC family devices and not for phone family devices
+ try
+ {
+ ApplicationViewSwitcher.DisableSystemViewActivationPolicy();
+ }
+ catch (Exception)
+ {
+ // Log that DisableSystemViewActionPolicy didn't work
+ }
+ }
+
+ // Create a Frame to act as the navigation context
+ rootFrame = App.CreateFrame();
+
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ if (!rootFrame.Navigate(typeof(MainPage), argument))
+ {
+ // We couldn't navigate to the main page, kill the app so we have a good
+ // stack to debug
+ throw new SystemException();
+ }
+
+ SetMinWindowSizeAndThemeAndActivate(rootFrame, minWindowSize);
+ m_mainViewId = ApplicationView.GetForCurrentView().Id;
+ AddWindowToMap(WindowFrameService.CreateNewWindowFrameService(rootFrame, false, weak));
+ }
+ else
+ {
+ // For first launch, LaunchStart is logged in constructor, this is for subsequent launches.
+
+ // !Phone check is required because even in continuum mode user interaction mode is Mouse not Touch
+ if ((UIViewSettings.GetForCurrentView().UserInteractionMode == UserInteractionMode.Mouse)
+ && (!Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")))
+ {
+ // If the pre-launch hasn't happened then allow for the new window/view creation
+ if (!m_preLaunched)
+ {
+ var newCoreAppView = CoreApplication.CreateNewView();
+ _ = newCoreAppView.Dispatcher.RunAsync(
+ CoreDispatcherPriority.Normal, async () =>
+ {
+ if (weak.Target is App that)
+ {
+ var newRootFrame = App.CreateFrame();
+
+ SetMinWindowSizeAndThemeAndActivate(newRootFrame, minWindowSize);
+
+ if (!newRootFrame.Navigate(typeof(MainPage), argument))
+ {
+ // We couldn't navigate to the main page, kill the app so we have a good
+ // stack to debug
+ throw new SystemException();
+ }
+
+ var frameService = WindowFrameService.CreateNewWindowFrameService(newRootFrame, true, weak);
+ that.AddWindowToMap(frameService);
+
+ var dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
+
+ // CSHARP_MIGRATION_ANNOTATION:
+ // class SafeFrameWindowCreation is being interpreted into a IDisposable class
+ // in order to enhance its RAII capability that was written in C++/CX
+ using (var safeFrameServiceCreation = new SafeFrameWindowCreation(frameService, that))
+ {
+ int newWindowId = ApplicationView.GetApplicationViewIdForWindow(CoreWindow.GetForCurrentThread());
+
+ ActivationViewSwitcher activationViewSwitcher = null;
+ var activateEventArgs = (args as IViewSwitcherProvider);
+ if (activateEventArgs != null)
+ {
+ activationViewSwitcher = activateEventArgs.ViewSwitcher;
+ }
+
+ if (activationViewSwitcher != null)
+ {
+ _ = activationViewSwitcher.ShowAsStandaloneAsync(newWindowId, ViewSizePreference.Default);
+ safeFrameServiceCreation.SetOperationSuccess(true);
+ }
+ else
+ {
+ var activatedEventArgs = (args as IApplicationViewActivatedEventArgs);
+ if ((activatedEventArgs != null) && (activatedEventArgs.CurrentlyShownApplicationViewId != 0))
+ {
+ // CSHARP_MIGRATION_ANNOTATION:
+ // here we don't use ContinueWith() to interpret origin code because we would like to
+ // pursue the design of class SafeFrameWindowCreate whichi was using RAII to ensure
+ // some states get handled properly when its instance is being destructed.
+ //
+ // To achieve that, SafeFrameWindowCreate has been reinterpreted using IDisposable
+ // pattern, which forces we use below way to keep async works being controlled within
+ // a same code block.
+ var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
+ frameService.GetViewId(),
+ ViewSizePreference.Default,
+ activatedEventArgs.CurrentlyShownApplicationViewId,
+ ViewSizePreference.Default);
+ // SafeFrameServiceCreation is used to automatically remove the frame
+ // from the list of frames if something goes bad.
+ safeFrameServiceCreation.SetOperationSuccess(viewShown);
+ }
+ }
+ }
+ }
+ });
+ }
+ else
+ {
+ ActivationViewSwitcher activationViewSwitcher = null;
+ var activateEventArgs = (args as IViewSwitcherProvider);
+ if (activateEventArgs != null)
+ {
+ activationViewSwitcher = activateEventArgs.ViewSwitcher;
+ }
+
+ if (activationViewSwitcher != null)
+ {
+ _ = activationViewSwitcher.ShowAsStandaloneAsync(
+ ApplicationView.GetApplicationViewIdForWindow(CoreWindow.GetForCurrentThread()), ViewSizePreference.Default);
+ }
+ else
+ {
+ TraceLogger.GetInstance().LogError(ViewMode.None, "App.OnAppLaunch", "Null_ActivationViewSwitcher");
+ }
+ }
+ // Set the preLaunched flag to false
+ m_preLaunched = false;
+ }
+ else // for touch devices
+ {
+ if (rootFrame.Content == null)
+ {
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ if (!rootFrame.Navigate(typeof(MainPage), argument))
+ {
+ // We couldn't navigate to the main page,
+ // kill the app so we have a good stack to debug
+ throw new SystemException();
+ }
+ }
+ if (ApplicationView.GetForCurrentView().ViewMode != ApplicationViewMode.CompactOverlay)
+ {
+ if (!Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
+ {
+ // for tablet mode: since system view activation policy is disabled so do ShowAsStandaloneAsync if activationViewSwitcher exists in
+ // activationArgs
+ ActivationViewSwitcher activationViewSwitcher = null;
+ var activateEventArgs = (args as IViewSwitcherProvider);
+ if (activateEventArgs != null)
+ {
+ activationViewSwitcher = activateEventArgs.ViewSwitcher;
+ }
+ if (activationViewSwitcher != null)
+ {
+ var viewId = (args as IApplicationViewActivatedEventArgs).CurrentlyShownApplicationViewId;
+ if (viewId != 0)
+ {
+ _ = activationViewSwitcher.ShowAsStandaloneAsync(viewId);
+ }
+ }
+ }
+ // Ensure the current window is active
+ Window.Current.Activate();
+ }
+ }
+ }
+ }
+
+ private void DismissedEventHandler(SplashScreen sender, object e)
+ {
+ _ = SetupJumpList();
+ }
+
+ private void RegisterDependencyProperties()
+ {
+ NarratorNotifier.RegisterDependencyProperties();
+ }
+
+ private void OnSuspending(object sender, SuspendingEventArgs args)
+ {
+ TraceLogger.GetInstance().LogButtonUsage();
+ }
+
+ private sealed class SafeFrameWindowCreation : IDisposable
+ {
+ public SafeFrameWindowCreation(WindowFrameService frameService, App parent)
+ {
+ m_frameService = frameService;
+ m_frameOpenedInWindow = false;
+ m_parent = parent;
+ }
+
+ public void SetOperationSuccess(bool success)
+ {
+ m_frameOpenedInWindow = success;
+ }
+
+ public void Dispose()
+ {
+ if (!m_frameOpenedInWindow)
+ {
+ // Close the window as the navigation to the window didn't succeed
+ // and this is not visible to the user.
+ m_parent.RemoveWindowFromMap(m_frameService.GetViewId());
+ }
+
+ GC.SuppressFinalize(this);
+ }
+
+ ~SafeFrameWindowCreation()
+ {
+ Dispose();
+ }
+
+ private readonly WindowFrameService m_frameService;
+ private bool m_frameOpenedInWindow;
+ private readonly App m_parent;
+ };
+
+ private async Task SetupJumpList()
+ {
+ try
+ {
+ var calculatorOptions = NavCategoryStates.CreateCalculatorCategoryGroup();
+
+ var jumpList = await JumpList.LoadCurrentAsync();
+ jumpList.SystemGroupKind = JumpListSystemGroupKind.None;
+ jumpList.Items.Clear();
+
+ foreach (NavCategory option in calculatorOptions.Categories)
+ {
+ if (!NavCategoryStates.IsViewModeEnabled(option.ViewMode))
+ {
+ continue;
+ }
+ ViewMode mode = option.ViewMode;
+ var item = JumpListItem.CreateWithArguments(((int)mode).ToString(), "ms-resource:///Resources/" + NavCategoryStates.GetNameResourceKey(mode));
+ item.Description = "ms-resource:///Resources/" + NavCategoryStates.GetNameResourceKey(mode);
+ item.Logo = new Uri("ms-appx:///Assets/" + mode + ".png");
+
+ jumpList.Items.Add(item);
+ }
+
+ await jumpList.SaveAsync();
+ }
+ catch
+ {
+ }
+ }
+
+ private async Task HandleViewReleaseAndRemoveWindowFromMap(WindowFrameService frameService)
+ {
+ WeakReference weak = new WeakReference(this);
+
+ // Unregister the event handler of the Main Page
+ var frame = (Window.Current.Content as Frame);
+ var mainPage = (frame.Content as MainPage);
+
+ mainPage.UnregisterEventHandlers();
+
+ await frameService.HandleViewRelease();
+ await Task.Run(() =>
+ {
+ var that = weak.Target as App;
+ that.RemoveWindowFromMap(frameService.GetViewId());
+ }).ConfigureAwait(false /* task_continuation_context::use_arbitrary() */);
+ }
+
+ private void AddWindowToMap(WindowFrameService frameService)
+ {
+ m_windowsMapLock.EnterWriteLock();
+ try
+ {
+ m_secondaryWindows[frameService.GetViewId()] = frameService;
+ TraceLogger.GetInstance().UpdateWindowCount(Convert.ToUInt64(m_secondaryWindows.Count));
+ }
+ finally
+ {
+ m_windowsMapLock.ExitWriteLock();
+ }
+ }
+
+ private WindowFrameService GetWindowFromMap(int viewId)
+ {
+ m_windowsMapLock.EnterReadLock();
+ try
+ {
+ if (m_secondaryWindows.TryGetValue(viewId, out var windowMapEntry))
+ {
+ return windowMapEntry;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ finally
+ {
+ m_windowsMapLock.ExitReadLock();
+ }
+ }
+
+ private void RemoveWindowFromMap(int viewId)
+ {
+ m_windowsMapLock.EnterWriteLock();
+ try
+ {
+ bool removed = m_secondaryWindows.Remove(viewId);
+ Debug.Assert(removed != false, "Window does not exist in the list");
+ }
+ finally
+ {
+ m_windowsMapLock.ExitWriteLock();
+ }
+ }
+
+ private readonly ReaderWriterLockSlim m_windowsMapLock = new ReaderWriterLockSlim();
+ private readonly Dictionary m_secondaryWindows = new Dictionary();
+ private int m_mainViewId;
+ private bool m_preLaunched;
+ }
+}
+
diff --git a/src/Calculator/App.xaml.h b/src/Calculator/App.xaml.h
deleted file mode 100644
index f11ebef6..00000000
--- a/src/Calculator/App.xaml.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-//
-// App.xaml.h
-// Declaration of the App class.
-//
-
-#pragma once
-
-#include "App.g.h"
-#include "WindowFrameService.h"
-
-namespace CalculatorApp
-{
- namespace ApplicationResourceKeys
- {
- extern Platform::StringReference AppMinWindowHeight;
- extern Platform::StringReference AppMinWindowWidth;
- }
-
- ///
- /// Provides application-specific behavior to supplement the default Application class.
- ///
- ref class App sealed
- {
- public:
- App();
- virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs ^ args) override;
- virtual void OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs ^ args) override;
-
- internal:
- void RemoveWindow(_In_ WindowFrameService ^ frameService);
- void RemoveSecondaryWindow(_In_ WindowFrameService ^ frameService);
-
- private:
- static Windows::UI::Xaml::Controls::Frame ^ CreateFrame();
- static void SetMinWindowSizeAndActivate(Windows::UI::Xaml::Controls::Frame ^ rootFrame, Windows::Foundation::Size minWindowSize);
-
- void OnAppLaunch(Windows::ApplicationModel::Activation::IActivatedEventArgs ^ args, Platform::String ^ argument);
- void DismissedEventHandler(Windows::ApplicationModel::Activation::SplashScreen ^ sender, Platform::Object ^ e);
- void RegisterDependencyProperties();
- void OnSuspending(Platform::Object ^ sender, Windows::ApplicationModel::SuspendingEventArgs ^ args);
-
-
- class SafeFrameWindowCreation final
- {
- public:
- SafeFrameWindowCreation(_In_ WindowFrameService ^ frameService, App ^ parent)
- : m_frameService(frameService)
- , m_frameOpenedInWindow(false)
- , m_parent(parent)
- {
- }
-
- void SetOperationSuccess(bool success)
- {
- m_frameOpenedInWindow = success;
- }
-
- ~SafeFrameWindowCreation()
- {
- if (!m_frameOpenedInWindow)
- {
- // Close the window as the navigation to the window didn't succeed
- // and this is not visible to the user.
- m_parent->RemoveWindowFromMap(m_frameService->GetViewId());
- }
- }
-
- private:
- WindowFrameService ^ m_frameService;
- bool m_frameOpenedInWindow;
- App ^ m_parent;
- };
-
- private:
- concurrency::reader_writer_lock m_windowsMapLock;
- std::unordered_map m_secondaryWindows;
-
- concurrency::task SetupJumpList();
- concurrency::task HandleViewReleaseAndRemoveWindowFromMap(_In_ WindowFrameService ^ frameService);
- void AddWindowToMap(_In_ WindowFrameService ^ frameService);
- WindowFrameService ^ GetWindowFromMap(int viewId);
- void RemoveWindowFromMap(int viewId);
- int m_mainViewId;
- bool m_preLaunched;
-
- Windows::UI::Xaml::Controls::Primitives::Popup ^ m_aboutPopup;
- };
-}
diff --git a/src/Calculator/Assets/CalcMDL2.ttf b/src/Calculator/Assets/CalcMDL2.ttf
deleted file mode 100644
index 9ee5deb0..00000000
Binary files a/src/Calculator/Assets/CalcMDL2.ttf and /dev/null differ
diff --git a/src/Calculator/Assets/CalculatorIcons.ttf b/src/Calculator/Assets/CalculatorIcons.ttf
new file mode 100644
index 00000000..176efcb9
Binary files /dev/null and b/src/Calculator/Assets/CalculatorIcons.ttf differ
diff --git a/src/Calculator/Calculator.csproj b/src/Calculator/Calculator.csproj
new file mode 100644
index 00000000..4f5693fb
--- /dev/null
+++ b/src/Calculator/Calculator.csproj
@@ -0,0 +1,849 @@
+
+
+
+
+ Debug
+ x86
+ {3B773403-B0D6-4F9A-948E-512A7A5FB315}
+ AppContainerExe
+ Properties
+ CalculatorApp
+ CalculatorApp
+ Windows Store
+ true
+ en-US
+ UAP
+ 10.0.22000.0
+ 10.0.17763.0
+
+ false
+ false
+ 14
+ 10.0
+ black
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ true
+ True
+ WindowsDev_TemporaryKey.pfx
+ False
+ Always
+ true
+ False
+ SHA256
+ False
+ True
+ $(Platform)
+ 0
+ /disableStackTraceMetadata /disableExceptionMessages
+
+
+
+ true
+ ..\x86\Debug\Calculator\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ ..\x86\Release\Calculator\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+ true
+ ..\ARM\Debug\Calculator\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ ..\ARM\Release\Calculator\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ ..\ARM64\Debug\Calculator\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ ARM64
+ false
+ prompt
+ true
+ true
+
+
+ ..\ARM64\Release\Calculator\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ ARM64
+ false
+ prompt
+ true
+ true
+
+
+ true
+ ..\x64\Debug\Calculator\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ ..\x64\Release\Calculator\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ $(DefineConstants);SEND_DIAGNOSTICS;IS_STORE_BUILD
+
+
+ PackageReference
+
+
+
+ App.xaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EquationStylePanelControl.xaml
+
+
+
+
+ Calculator.xaml
+
+
+ CalculatorProgrammerBitFlipPanel.xaml
+
+
+ CalculatorProgrammerOperators.xaml
+
+
+ CalculatorProgrammerRadixOperators.xaml
+
+
+ CalculatorScientificAngleButtons.xaml
+
+
+ CalculatorScientificOperators.xaml
+
+
+ CalculatorStandardOperators.xaml
+
+
+ DateCalculator.xaml
+
+
+ EquationInputArea.xaml
+
+
+ GraphingCalculator.xaml
+
+
+ GraphingNumPad.xaml
+
+
+ GraphingSettings.xaml
+
+
+ KeyGraphFeaturesPanel.xaml
+
+
+ HistoryList.xaml
+
+
+ MainPage.xaml
+
+
+
+
+
+ Memory.xaml
+
+
+ MemoryListItem.xaml
+
+
+ NumberPad.xaml
+
+
+ OperatorsPanel.xaml
+
+
+ Settings.xaml
+
+
+
+ CalculatorProgrammerDisplayPanel.xaml
+
+
+
+ SupplementaryResults.xaml
+
+
+ TitleBar.xaml
+
+
+ UnitConverter.xaml
+
+
+
+
+
+ Designer
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+ 0.0.16
+
+
+ 6.2.14
+
+
+
+
+
+ {812d1a7b-b8ac-49e4-8e6d-af5d59500d56}
+ CalcViewModel
+
+
+ {e727a92b-f149-492c-8117-c039a298719b}
+ GraphControl
+
+
+ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}
+ TraceLogging
+
+
+
+
+
+
+
+ 14.0
+
+
+
+
+ <_IntermediateFrameworkSdkReference Include="@(AppxPackageRegistration)" Condition="'@(AppxPackageRegistration)' != ''
AND ('$(Configuration)' == '%(AppxPackageRegistration.Configuration)' OR '%(AppxPackageRegistration.Configuration)' == '')
AND ('$(PlatformTarget)' == '%(AppxPackageRegistration.Architecture)' OR '%(AppxPackageRegistration.Configuration)' == '')">
+ %(AppxPackageRegistration.Name)
+ %(AppxPackageRegistration.Filename)
+ %(AppxPackageRegistration.Configuration)
+ %(AppxPackageRegistration.Architecture)
+ %(AppxPackageRegistration.Identity)
+
+
+ Name = %(_IntermediateFrameworkSdkReference.SDKName), MinVersion = %(_IntermediateFrameworkSdkReference.Version), Publisher = %(_IntermediateFrameworkSdkReference.Publisher)
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj
deleted file mode 100644
index 4724d1fc..00000000
--- a/src/Calculator/Calculator.vcxproj
+++ /dev/null
@@ -1,969 +0,0 @@
-
-
-
- {9447424a-0e05-4911-beb8-e0354405f39a}
- CalculatorApp
- en-US
- 15.0
- true
- Windows Store
- 10.0.18362.0
- 10.0.17134.0
-
- false
- false
- 10.0
- black
- Always
- WindowsDev_TemporaryKey.pfx
- True
- False
-
-
-
-
- x64
-
-
-
- Debug
- ARM
-
-
- Debug
- ARM64
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- ARM
-
-
- Release
- ARM64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- Application
- true
- v142
-
-
- Application
- true
- v142
-
-
- Application
- true
- v142
-
-
- Application
- true
- v142
-
-
- Application
- false
- true
- v142
-
-
- Application
- false
- true
- v142
-
-
- Application
- false
- true
- v142
-
-
- Application
- false
- true
- v142
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
- 4453;28204
- $(SolutionDir)..\src\;%(AdditionalIncludeDirectories)
- Level4
- true
-
-
-
-
- /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
- 4453;28204
- $(SolutionDir)..\src\;%(AdditionalIncludeDirectories)
- Level4
- true
-
-
-
-
- /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
- 4453;28204
- $(SolutionDir)..\src\;%(AdditionalIncludeDirectories)
- Level4
- true
-
-
- WindowsApp.lib;$(VC_ReferencesPath_VC_ARM)\pgort.lib;%(AdditionalDependencies)
-
-
-
-
- /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
- 4453;28204
- $(SolutionDir)..\src\;%(AdditionalIncludeDirectories)
- Level4
- true
-
-
- WindowsApp.lib;$(VC_ReferencesPath_VC_ARM)\pgort.lib;%(AdditionalDependencies)
-
-
-
-
- /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
- 4453;28204
- $(SolutionDir)..\src\;%(AdditionalIncludeDirectories)
- Level4
- true
-
-
-
-
- /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
- 4453;28204
- $(SolutionDir)..\src\;%(AdditionalIncludeDirectories)
- Level4
- true
-
-
- WindowsApp.lib;$(VC_ReferencesPath_VC_x86)\pgort.lib;%(AdditionalDependencies)
-
-
-
-
- /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
- 4453;28204
- $(SolutionDir)..\src\;%(AdditionalIncludeDirectories)
- Level4
- true
-
-
-
-
- /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
- 4453;28204
- $(SolutionDir)..\src\;%(AdditionalIncludeDirectories)
- Level4
- true
-
-
- WindowsApp.lib;$(VC_ReferencesPath_VC_x64)\pgort.lib;%(AdditionalDependencies)
-
-
-
-
- /DSEND_DIAGNOSTICS /DIS_STORE_BUILD %(AdditionalOptions)
-
-
-
- 0.0.0.0
-
-
- true
-
-
-
-
-
-
- AboutFlyout.xaml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- App.xaml
-
-
- EquationStylePanelControl.xaml
-
-
-
-
- Views\Calculator.xaml
-
-
- Views\CalculatorProgrammerBitFlipPanel.xaml
-
-
- Views\CalculatorProgrammerDisplayPanel.xaml
-
-
- Views\CalculatorProgrammerOperators.xaml
-
-
- Views\CalculatorProgrammerRadixOperators.xaml
-
-
- Views\CalculatorScientificAngleButtons.xaml
-
-
- Views\CalculatorScientificOperators.xaml
-
-
- Views\CalculatorStandardOperators.xaml
-
-
- Views\GraphingCalculator\EquationInputArea.xaml
-
-
- Views\GraphingCalculator\GraphingCalculator.xaml
-
-
- Views\GraphingCalculator\GraphingSettings.xaml
-
-
- Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml
-
-
- Views\GraphingCalculator\GraphingNumPad.xaml
-
-
- Views\HistoryList.xaml
-
-
- Views\MainPage.xaml
-
-
- Views\Memory.xaml
-
-
- Views\MemoryListItem.xaml
-
-
- Views\NumberPad.xaml
-
-
- Views\OperatorsPanel.xaml
-
-
-
-
- Views\SupplementaryResults.xaml
-
-
- Views\DateCalculator.xaml
-
-
- Views\TitleBar.xaml
-
-
- Views\UnitConverter.xaml
-
-
-
-
-
- Designer
-
-
-
- Designer
-
-
- Designer
-
-
- Designer
-
-
-
-
- Designer
-
-
-
- Designer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Designer
-
-
- Designer
-
-
-
-
-
- AboutFlyout.xaml
-
-
- App.xaml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Create
- Create
- Create
- Create
- Create
- Create
- Create
- Create
-
-
- EquationStylePanelControl.xaml
-
-
-
-
- Views\Calculator.xaml
-
-
- Views\CalculatorProgrammerBitFlipPanel.xaml
-
-
- Views\CalculatorProgrammerDisplayPanel.xaml
-
-
- Views\CalculatorProgrammerOperators.xaml
-
-
- Views\CalculatorProgrammerRadixOperators.xaml
-
-
- Views\CalculatorScientificAngleButtons.xaml
-
-
- Views\CalculatorScientificOperators.xaml
-
-
- Views\CalculatorStandardOperators.xaml
-
-
- Views\GraphingCalculator\EquationInputArea.xaml
-
-
- Views\GraphingCalculator\GraphingCalculator.xaml
-
-
- Views\GraphingCalculator\GraphingSettings.xaml
-
-
- Views\GraphingCalculator\KeyGraphFeaturesPanel.xaml
-
-
- Views\GraphingCalculator\GraphingNumPad.xaml
-
-
- Views\HistoryList.xaml
-
-
- Views\MainPage.xaml
-
-
- Views\Memory.xaml
-
-
- Views\MemoryListItem.xaml
-
-
- Views\NumberPad.xaml
-
-
- Views\OperatorsPanel.xaml
-
-
-
-
- Views\SupplementaryResults.xaml
-
-
- Views\DateCalculator.xaml
-
-
- Views\TitleBar.xaml
-
-
- Views\UnitConverter.xaml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Designer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
-
-
-
-
- {90e9761d-9262-4773-942d-caeae75d7140}
-
-
- {e727a92b-f149-492c-8117-c039a298719b}
-
-
-
-
-
-
- <_IntermediateFrameworkSdkReference Include="@(AppxPackageRegistration)" Condition="'@(AppxPackageRegistration)' != ''
AND ('$(Configuration)' == '%(AppxPackageRegistration.Configuration)' OR '%(AppxPackageRegistration.Configuration)' == '')
AND ('$(PlatformTarget)' == '%(AppxPackageRegistration.Architecture)' OR '%(AppxPackageRegistration.Configuration)' == '')">
- %(AppxPackageRegistration.Name)
- %(AppxPackageRegistration.Filename)
- %(AppxPackageRegistration.Configuration)
- %(AppxPackageRegistration.Architecture)
- %(AppxPackageRegistration.Identity)
-
-
- Name = %(_IntermediateFrameworkSdkReference.SDKName), MinVersion = %(_IntermediateFrameworkSdkReference.Version), Publisher = %(_IntermediateFrameworkSdkReference.Publisher)
-
-
-
-
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see https://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
\ No newline at end of file
diff --git a/src/Calculator/Calculator.vcxproj.filters b/src/Calculator/Calculator.vcxproj.filters
deleted file mode 100644
index 790f6623..00000000
--- a/src/Calculator/Calculator.vcxproj.filters
+++ /dev/null
@@ -1,1569 +0,0 @@
-
-
-
-
- 9447424a-0e05-4911-beb8-e0354405f39a
-
-
- c853ff75-910d-48f0-ac19-d5fd57622aba
- bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png
-
-
- {21d65f04-31c9-4c70-8511-1c65b894ac8b}
-
-
- {5a666ef7-54fb-46cc-9588-5cbcfaed3465}
-
-
- {f9b88d9e-918b-49ac-869b-a1a380ec3201}
-
-
- {6c2951d4-aa9a-44ce-88c5-28fe11b4e7f7}
-
-
- {7794e615-088b-412c-88bf-f045788ca81f}
-
-
- {72128df8-67df-4d34-934d-14896720e153}
-
-
- {9dd1aaa8-31a9-43b3-b224-77293910f109}
-
-
- {4fc9f4fc-51a7-4348-881b-efe9b32cd0bc}
-
-
- {c883c196-cbc3-437f-8dbd-92f3009479c1}
-
-
- {399ad3d6-a676-45a5-ad0e-8bf796ecfea8}
-
-
- {ad7f2c92-59aa-4720-96af-fccfa1530b25}
-
-
- {b5e4250c-03cf-4cef-ae64-67205e3cdca7}
-
-
- {7ca47758-c39c-40f9-8cbb-7fc2fb627c9e}
-
-
- {65e8bdb6-ca86-43b8-a335-ee406bffe79b}
-
-
- {f47b0870-721f-4646-8b9f-2e55613bcbcc}
-
-
- {9ba8ec65-5ba8-4499-add4-b085710f5ef4}
-
-
- {55225802-0eb4-4d30-91ba-025ac695c7b2}
-
-
- {582f1542-e30b-461d-bf1e-33af9cbd2241}
-
-
- {1fa74901-4f66-4eb1-8d17-fa46debcf314}
-
-
- {2a4bc64b-d709-46a1-9913-006dbf545ff3}
-
-
- {05ba3255-5c3f-4a1f-a8a2-8984cd7826f0}
-
-
- {dc6243aa-fe4d-46e3-9c31-f8461e7bb007}
-
-
- {5dc497d8-4b4d-4851-a721-e37585fcb4ed}
-
-
- {8945e63d-27c4-4407-81bb-993f78b583d8}
-
-
- {a3c3e799-4fff-4795-9ef7-ee2237c4c190}
-
-
- {41958465-ab1b-4450-a688-c2a49a476ad3}
-
-
- {3cb02368-06c6-46b2-a2b3-be916140f2df}
-
-
- {f9dede5d-08b1-4c18-8967-2bf6e0eab10a}
-
-
- {a1cd3ced-b21b-47a1-9dad-5f9a3bcb0653}
-
-
- {99bbda66-7ed8-48e4-bc8b-9285d9c22fb0}
-
-
- {7d443f1c-4e49-4379-bd5c-dd156a73bbb7}
-
-
- {7353aa9e-8f6d-4b11-885b-cb41e8deeb55}
-
-
- {7737b4aa-a25f-464d-8f41-4c7420363963}
-
-
- {a4f2f71c-0707-44df-a8d7-8bf085fc4ace}
-
-
- {16a3847d-fcd8-48ec-af99-0eba690b3389}
-
-
- {decf69bc-1143-4e7e-bf8c-a78201f541c0}
-
-
- {c511e187-9ffa-40ec-8d8b-7d89048ed33e}
-
-
- {9d8d84e4-347a-40d6-bea7-82919c544cdc}
-
-
- {50aa51a9-ac6a-4f46-9920-4fcbb34cab31}
-
-
- {35d8beb6-382f-4e05-a3f0-e21555076168}
-
-
- {cfd9f17a-dcf5-4ab7-9a4d-f66b0a89a21b}
-
-
- {1c96ea43-c29b-4d91-905f-9a80fe3a8ce3}
-
-
- {be692687-c3d8-4ebf-9200-2325a2a7f5c1}
-
-
- {6edbff29-bb0a-4a31-9d21-ac4904cf15db}
-
-
- {38c626d1-54b4-4162-9650-755fb95da2e7}
-
-
- {7caf3ffa-9430-49d4-86da-ef6fd3b952ec}
-
-
- {ea5e3c91-ae7b-4984-8f67-a287dc4e985d}
-
-
- {b8904687-7060-450e-8ac6-22b409acb0ff}
-
-
- {bde6a2ee-9103-45ad-a03c-840405419d96}
-
-
- {2ecb3b06-467c-4872-9df9-910752d5a0e5}
-
-
- {75c19928-73ca-4451-ac27-7c87df9f5add}
-
-
- {6623c7a9-1632-4776-bd26-e924d8bdc032}
-
-
- {392e6638-a46c-463f-a76c-d80ea6dafb76}
-
-
- {f5b473d1-ff89-4278-bc40-f842a5f25b31}
-
-
- {90ffae6c-249f-40bb-b817-857136971b44}
-
-
- {cada420a-1c49-4446-972e-b3e099773c53}
-
-
- {f829702a-28db-47eb-95ca-c424ec052101}
-
-
- {1b77ab20-2528-42c9-931b-4de4d6b872fb}
-
-
- {c3930ca9-93d7-401c-898f-523590a400c9}
-
-
- {aa0bf861-fe20-4cad-b78b-cf037bcb1f2c}
-
-
- {d429fed0-d5d8-49a3-a7c8-2f7c45cf789f}
-
-
- {d81d9186-d538-4a6e-95aa-1c84bbd0c2a4}
-
-
- {8647b869-c857-4e75-97ab-726cf7e041c5}
-
-
- {d443fa37-c49e-47d2-9697-928617752438}
-
-
- {c83b2fa0-f69b-40e7-90e2-1a9c02ed2681}
-
-
- {2075e31f-992a-4ec5-8671-2c4e244f1285}
-
-
- {d9d114cf-2268-4954-93f8-97a9dad6bdd4}
-
-
- {3cb2e2cf-48be-4c9c-96b8-0c843c73e0fa}
-
-
- {fb46a60d-1f3a-4818-aefd-cba41e514245}
-
-
- {0120c344-0bc0-4a1d-b82c-df7945f46189}
-
-
- {e23e2a6e-491b-4200-9bf7-d355a1ee695b}
-
-
- {b491a249-26b8-4814-9f50-2c3a57018c56}
-
-
-
-
-
-
-
-
-
- Controls
-
-
- Controls
-
-
- Controls
-
-
- Converters
-
-
- Converters
-
-
- Converters
-
-
- Converters
-
-
- Converters
-
-
- Converters
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Controls
-
-
-
-
- Controls
-
-
-
-
- Controls
-
-
- Controls
-
-
- Views\StateTriggers
-
-
-
-
- Controls
-
-
- Common
-
-
- Controls
-
-
-
- Views\StateTriggers
-
-
- Controls
-
-
- Controls
-
-
-
-
- Controls
-
-
-
- Views\GraphingCalculator
-
-
-
- Utils
-
-
- Common
-
-
-
-
-
-
-
-
- Common
-
-
- Controls
-
-
- Controls
-
-
- Controls
-
-
- Converters
-
-
- Converters
-
-
- Converters
-
-
- Converters
-
-
- Converters
-
-
- Converters
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Controls
-
-
-
-
- Controls
-
-
-
-
- Controls
-
-
- Controls
-
-
- Views\StateTriggers
-
-
-
-
- Controls
-
-
- Common
-
-
- Controls
-
-
- Views\StateTriggers
-
-
-
- Controls
-
-
- Controls
-
-
-
-
- Controls
-
-
-
- Views\GraphingCalculator
-
-
-
- Utils
-
-
- Common
-
-
- Common
-
-
-
-
-
-
-
-
-
-
-
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views
-
-
- Views\GraphingCalculator
-
-
- Views\GraphingCalculator
-
-
- Views
-
-
- Views\GraphingCalculator
-
-
- Views\GraphingCalculator
-
-
- Views\GraphingCalculator
-
-
-
- Views\StateTriggers
-
-
-
-
- Resources\en-US
-
-
- Resources\en-US
-
-
- Resources\az-Latn-az
-
-
- Resources\af-za
-
-
- Resources\uk-ua
-
-
- Resources\ar-sa
-
-
- Resources\vi-vn
-
-
- Resources\am-et
-
-
- Resources\tr-tr
-
-
- Resources\zh-tw
-
-
- Resources\bg-bg
-
-
- Resources\ca-es
-
-
- Resources\cs-cz
-
-
- Resources\da-dk
-
-
- Resources\zh-cn
-
-
- Resources\ta-in
-
-
- Resources\sv-se
-
-
- Resources\te-in
-
-
- Resources\th-th
-
-
- Resources\et-ee
-
-
- Resources\es-mx
-
-
- Resources\sk-sk
-
-
- Resources\el-gr
-
-
- Resources\en-gb
-
-
- Resources\de-de
-
-
- Resources\sr-latn-rs
-
-
- Resources\es-es
-
-
- Resources\sq-al
-
-
- Resources\fil-ph
-
-
- Resources\ru-ru
-
-
- Resources\fr-ca
-
-
- Resources\sl-sI
-
-
- Resources\nl-nl
-
-
- Resources\nb-no
-
-
- Resources\eu-es
-
-
- Resources\fa-ir
-
-
- Resources\fi-fi
-
-
- Resources\ro-ro
-
-
- Resources\he-il
-
-
- Resources\fr-fr
-
-
- Resources\gl-es
-
-
- Resources\pl-pl
-
-
- Resources\pt-pt
-
-
- Resources\hi-in
-
-
- Resources\pt-br
-
-
- Resources\lt-lt
-
-
- Resources\ms-my
-
-
- Resources\it-it
-
-
- Resources\mk-mk
-
-
- Resources\lv-lv
-
-
- Resources\ja-jp
-
-
- Resources\id-id
-
-
- Resources\ml-in
-
-
- Resources\hr-hr
-
-
- Resources\kn-in
-
-
- Resources\hu-hu
-
-
- Resources\is-is
-
-
- Resources\ko-kr
-
-
- Resources\lo-la
-
-
- Resources\km-kh
-
-
- Resources\kk-kz
-
-
- Resources\es-mx
-
-
- Resources\fr-ca
-
-
- Resources\is-is
-
-
- Resources\km-kh
-
-
- Resources\id-id
-
-
- Resources\it-it
-
-
- Resources\ms-my
-
-
- Resources\hr-hr
-
-
- Resources\mk-mk
-
-
- Resources\ml-in
-
-
- Resources\lv-lv
-
-
- Resources\fr-fr
-
-
- Resources\hi-in
-
-
- Resources\lt-lt
-
-
- Resources\hu-hu
-
-
- Resources\he-il
-
-
- Resources\pt-pt
-
-
- Resources\gl-es
-
-
- Resources\pt-br
-
-
- Resources\eu-es
-
-
- Resources\fa-ir
-
-
- Resources\nb-no
-
-
- Resources\pl-pl
-
-
- Resources\nl-nl
-
-
- Resources\et-ee
-
-
- Resources\sq-al
-
-
- Resources\ro-ro
-
-
- Resources\ru-ru
-
-
- Resources\lo-la
-
-
- Resources\fil-ph
-
-
- Resources\sk-sk
-
-
- Resources\fi-fi
-
-
- Resources\de-de
-
-
- Resources\sr-latn-rs
-
-
- Resources\en-gb
-
-
- Resources\te-in
-
-
- Resources\kn-in
-
-
- Resources\th-th
-
-
- Resources\ta-in
-
-
- Resources\es-es
-
-
- Resources\sv-se
-
-
- Resources\el-gr
-
-
- Resources\uk-ua
-
-
- Resources\zh-cn
-
-
- Resources\vi-vn
-
-
- Resources\tr-tr
-
-
- Resources\sl-sI
-
-
- Resources\zh-tw
-
-
- Resources\cs-cz
-
-
- Resources\da-dk
-
-
- Resources\bg-bg
-
-
- Resources\ca-es
-
-
- Resources\az-Latn-az
-
-
- Resources\af-za
-
-
- Resources\ar-sa
-
-
- Resources\kk-kz
-
-
- Resources\am-et
-
-
- Resources\ja-jp
-
-
- Resources\ko-kr
-
-
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
- Assets
-
-
-
-
- Assets
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Calculator/Common/AlwaysSelectedCollectionView.cs b/src/Calculator/Common/AlwaysSelectedCollectionView.cs
new file mode 100644
index 00000000..21e7b8f0
--- /dev/null
+++ b/src/Calculator/Common/AlwaysSelectedCollectionView.cs
@@ -0,0 +1,219 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml.Data;
+
+namespace CalculatorApp
+{
+ namespace Common
+ {
+ internal sealed class AlwaysSelectedCollectionView : Windows.UI.Xaml.DependencyObject, Windows.UI.Xaml.Data.ICollectionView
+ {
+ internal AlwaysSelectedCollectionView(IList source)
+ {
+ CurrentPosition = -1;
+ m_source = source;
+
+ if (source is Windows.UI.Xaml.Interop.IBindableObservableVector observable)
+ {
+ observable.VectorChanged += OnSourceBindableVectorChanged;
+ }
+ }
+
+ public bool MoveCurrentTo(object item)
+ {
+ if (item != null)
+ {
+ int newCurrentPosition = m_source.IndexOf(item);
+ if (newCurrentPosition != -1)
+ {
+ CurrentPosition = newCurrentPosition;
+ CurrentChanged?.Invoke(this, null);
+ return true;
+ }
+ }
+
+ // The item is not in the collection
+ // We're going to schedule a call back later so we
+ // restore the selection to the way we wanted it to begin with
+ if (CurrentPosition >= 0 && CurrentPosition < m_source.Count)
+ {
+ Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ CurrentChanged?.Invoke(this, null);
+ }).AsTask().Wait();
+ }
+ return false;
+ }
+
+ public bool MoveCurrentToPosition(int index)
+ {
+ if (index < 0 || index >= m_source.Count)
+ {
+ return false;
+ }
+
+ CurrentPosition = index;
+ CurrentChanged?.Invoke(this, null);
+ return true;
+ }
+
+ #region no implementations
+
+ public bool MoveCurrentToFirst()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool MoveCurrentToLast()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool MoveCurrentToNext()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool MoveCurrentToPrevious()
+ {
+ throw new NotImplementedException();
+ }
+
+ public IAsyncOperation LoadMoreItemsAsync(uint count)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Insert(int index, object item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void RemoveAt(int index)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Add(object item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Clear()
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Contains(object item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void CopyTo(object[] array, int arrayIndex)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Remove(object item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsReadOnly => throw new NotImplementedException();
+
+ #endregion no implementations
+
+ public object this[int index]
+ {
+ get => m_source[index];
+
+ set => throw new NotImplementedException();
+ }
+
+ public int Count => m_source.Count;
+
+ public IObservableVector