Compare commits

...

30 Commits

Author SHA1 Message Date
Niels Laute
fb8197bd5a Update SettingsPageControl.xaml 2025-09-19 13:53:23 +02:00
Niels Laute
70c4016860 Adding inline docs 2025-09-18 15:58:17 +02:00
Jiří Polášek
fef6921d9b CmdPal: Bind FilterDropDown selection to the current filter and ensure notifications are raised on UI thread (#41808)
## Summary of the Pull Request

This PR declaratively binds FilterDropDown.SelectedValue to
CurrentFilterId (one-way only; updates in the opposite direction are
handled within the drop-down’s code). It also removes observable
properties and reverts to the UpdateProperty style to ensure property
change notifications are raised on the UI thread, aligning the handling
style with other classes.

## Impact
- Fixed a crash that could occur on pages with filters
- The filter drop-down now correctly syncs with the initially selected
filter when loading a page

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #41578
- [x] Closes: #41649
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2025-09-18 15:51:22 +02:00
Kai Tao
ba1eb08c1f Runner: fix sln structure (#41841)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Common project was put into dsc folder by mistake, move it back to root
folder of powertoys

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
Visual studio build successfully

- [ ] Closes: #xxx
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Build success
2025-09-18 15:51:21 +02:00
Alex Mihaiuc
480049388d Update ZoomIt.rc for Sysinternals standalone v9.01 (#41833)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
This pull request updates the template resource file to improve
discoverability of strings from the standalone ZoomIt. This change is
intended to help other contributors more easily find and manage
localization strings and text resources associated with ZoomIt.

* Updated the displayed version in the ZoomIt UI from "v9.0" to "v9.01"
(`src/modules/ZoomIt/ZoomIt/ZoomIt.rc`).
* Updated the copyright year from 2024 to 2025 in the ZoomIt UI
(`src/modules/ZoomIt/ZoomIt/ZoomIt.rc`).

- [ ] Closes: #xxx
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

- Updated the template resource file with clearer references to strings
used in the standalone ZoomIt application.
- No functional code changes; this is strictly a resource/template
update.
- Aids contributors in locating and editing UI text, error messages, and
other localizable strings.

It could be challenging for contributors to understand which version of
PowerToys correlates with the standalone ZoomIt from sysinternals.com.
By updating the template resource file, we streamline the process for
future edits, translations, and maintenance.

## Validation Steps Performed

There is no validation required, as the values in the dialog get
dynamically generated/set at runtime, this is just so that contributors
can easily cross-reference versions with the standalone sysinternals.com
ZoomIt release.
2025-09-18 15:51:19 +02:00
Jiří Polášek
e505d68b9a CmdPal: Prevent crash on duplicate keybindings; simplify matching (#41714)
## Summary of the Pull Request

Handles duplicate keybindings by using the first occurrence and ignoring
the rest (in `ContextMenuViewModel.Keybindings` and
`IContextMenuContext.Keybindings`).

Replaces LINQ with direct iteration for clarity.

Simplifies `CheckKeybinding` by removing redundant null checks and
clarifying the key-to-binding matching logic, improving both readability
and efficiency.

Add a new method to `KeyChordHelpers.FormatForDebug` that formats
KeyChord as string to help debugging.

Makes `KeyChordHelpers` class a static class.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #41712
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [x] **Dev docs:** Added/updated
- [x] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [x] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

Validated using a custom extension that has a duplicate item in the
context menu.
2025-09-18 15:51:16 +02:00
Mike Griese
49a6bdc889 CmdPal: prevent ctrl+i from inserting a tab (#41746)
Eat the Ctrl+I, so that it doesn't insert a tab. Why does it insert a
tab? Who knows.

closes #41681
2025-09-18 15:51:14 +02:00
Jiří Polášek
a6785ad87c CmdPal: Remove transition animation from filter drop-down and set minimum width (#41832)
## Summary of the Pull Request

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #41651 
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2025-09-18 15:51:13 +02:00
Jiří Polášek
bea563474b CmdPal: Fix filter separators (two in one) (#41834)
## Summary of the Pull Request

Drop-in fix for two issues with search filter separators:
- Separator visual template is not applied when AOT compilation is
enabled.
- Separator template uses a different brush then other separators.

Pictures? Pictures!

<img width="935" height="1178" alt="image"
src="https://github.com/user-attachments/assets/d4fcb5a8-1610-4972-adc3-9f301cb2ed50"
/>


## PR Checklist

- [x] Closes: #41441 
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2025-09-18 15:51:13 +02:00
Sam Rueby
643bba087c Use shape icons for Command Palette Windows Service state. (#41809)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary
Resolves #41653 by using play/pause/stop icons for Windows Service state
in the Command Palette utility. Prior to this green/red circles were
used. New icons provide an improved user experience, especially for
color-blind users. The new icons are consistent with the UI in the
native Windows Services management console utility (services.msc).

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ X ] Closes: #41653
- [ X ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Windows service states display new icons:
<img width="901" height="549" alt="image"
src="https://github.com/user-attachments/assets/3265ff3c-b5ab-4c58-9922-1b7fc0e7c76d"
/>
<img width="894" height="594" alt="image"
src="https://github.com/user-attachments/assets/cffad0b4-5c31-4e63-afe0-630a94ed8379"
/>

Here is an image of how the icons currently appear prior to working on
this PR.
<img width="871" height="596" alt="image"
src="https://github.com/user-attachments/assets/e7a6ca81-5dc5-413d-b9d2-055c00c77ad3"
/>
2025-09-18 15:51:11 +02:00
chakrik73
4375f0439c zoomit bug fixes (#41773)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #41040, #41041, #41043
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Manually tested and ensured that the issues are
resolved.
- [ ] **Localization:** N/A
- [ ] **Dev docs:** N/A
- [ ] **New binaries:** No new binaries added
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
This PR includes code-changes to restore some of the features of ZoomIt
that existed in older versions and lost in later versions, such as when
in Draw mode, after drawing, if an area is snipped, it doesn't clear the
drawing immediately, giving the user an option to cancel snip and update
the drawing. Also, in draw mode, when left mouse is clicked, it results
in a dot, as it was in previous versions. This PR also addresses some
race conditions during Recording that results in error when the
Recording is saved.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manually tested and validated the draw and snip modes.
2025-09-18 15:51:11 +02:00
Guilherme
466013dad9 CmdPal: Fix EmptyContent not rendering (#41788)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
While testing the recent GridPages changes #40832 , I noticed that the
`EmptyContent` case was removed from the `SwitchPresenter`, which caused
EmptyContent to stop rendering.

This PR restores the missing case so that `EmptyContent` is correctly
displayed again.

### Before
<img width="790" height="480" alt="BeforeFix"
src="https://github.com/user-attachments/assets/71e43da9-41c4-4c1a-bbb1-bc3f6b4da1d0"
/>

### After
<img width="793" height="483" alt="AfterFix"
src="https://github.com/user-attachments/assets/ebec6b44-ebfd-4497-9e69-99b00ce44117"
/>


<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #41786 
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2025-09-18 15:51:11 +02:00
Davide Giacometti
f4d3cfb951 [Settings] Search Results Page Improvements (#41719)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

- Fix tab navigation issues #41717
- Minor improvement:
  - Show module group only if there are modules to show #41526
  - Add line break in the "no results" message

0.94
<img width="769" height="422" alt="image"
src="https://github.com/user-attachments/assets/111fc200-5811-43aa-9ea0-3f8d80543560"
/>

PR
<img width="812" height="524" alt="image"
src="https://github.com/user-attachments/assets/65070862-ff3f-4294-8aad-2ade4e6d4e90"
/>

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #41717 #41526
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

- Verified that tab navigation is smooth between search groups
- Verified that narrator announces group names
- Tested empty search results page
2025-09-18 15:51:09 +02:00
Kai Tao
8ad322dab3 Dev doc: Work in vscode (#41704)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Doc and debugging setting in vscode.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
This pull request adds support for developing and debugging PowerToys
using Visual Studio Code by introducing a new launch configuration and
comprehensive developer documentation. These changes make it easier for
contributors to build, debug, and iterate on both native and managed
components of PowerToys within VS Code.

**VS Code integration and developer workflow:**

* Added `.vscode/launch.json` with configurations for launching and
attaching to native (`PowerToys.exe`) and managed
(`PowerToys.Settings.exe`) processes, supporting both C++ and .NET
debugging scenarios.
* Introduced `doc/devdocs/development/dev-with-vscode.md`, a detailed
guide covering VS Code setup, building, debugging, and common developer
workflows for the PowerToys project. This includes extension
recommendations, shell integration, sample build commands, and
troubleshooting tips.
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Can debug locally in vscode

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-18 15:51:08 +02:00
leileizhang
d382966150 [UI Tests] Stabilize Mouse Utils UI tests by switching to AccessibilityId (#41755)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
The Mouse Utils UI tests were failing because the Name values changed.

This PR updates the tests to use AccessibilityId instead, which provides
more stable element identification.

try to replace all findbyname

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2025-09-18 15:51:07 +02:00
Niels Laute
437ca174d4 Update OobeWhatsNew.xaml 2025-09-10 19:18:33 +02:00
Niels Laute
c9642c3c68 Move md config to XAML 2025-09-10 19:06:41 +02:00
Niels Laute
3eea52d062 Fixing build errors 2025-09-10 19:06:30 +02:00
Niels Laute
5bc1644882 XAML styler 2025-09-10 17:23:31 +02:00
Niels Laute
06ea71b57d Update OobeWhatsNew.xaml 2025-09-10 17:19:14 +02:00
Niels Laute
04c73f6ff1 xaml formatting 2025-09-10 17:08:24 +02:00
Niels Laute
039e3d924c Fixes 2025-09-10 16:50:56 +02:00
Niels Laute
280c3642be Upgrading MarkdownTextBlock package + namespaces 2025-09-10 16:38:06 +02:00
Niels Laute
4806b145f0 XAML styler 2025-09-10 14:42:24 +02:00
Niels Laute
84d492a92e Update NOTICE.md 2025-09-10 14:41:50 +02:00
Niels Laute
1e5fde68a8 Remove 7.x package 2025-09-10 14:33:27 +02:00
Niels Laute
85d8fbdabd [CmdPal] Remove unused namespace 2025-09-10 14:32:05 +02:00
Niels Laute
eba0b9c619 [Registry Preview] Remove unused namespaces 2025-09-10 14:31:49 +02:00
Niels Laute
8f029db21e More Settings fixes 2025-09-10 14:30:51 +02:00
Niels Laute
9081f98de6 Replacing MarkdownTextBlock and WrapPanel in Settings 2025-09-10 14:27:53 +02:00
76 changed files with 1370 additions and 373 deletions

View File

@@ -247,6 +247,7 @@ CONFIGW
CONFLICTINGMODIFIERKEY
CONFLICTINGMODIFIERSHORTCUT
CONOUT
coreclr
constexpr
contentdialog
contentfiles
@@ -268,6 +269,8 @@ cpcontrols
cph
cplusplus
CPower
cpptools
cppvsdbg
cppwinrt
createdump
CREATEPROCESS
@@ -279,6 +282,7 @@ CRH
critsec
cropandlock
Crossdevice
csdevkit
CSearch
CSettings
cso
@@ -2012,6 +2016,7 @@ XButton
xclip
xcopy
XDeployment
xdf
XDocument
XElement
xfd

43
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,43 @@
{
"version": "0.2.0",
"inputs": [
{
"id": "arch",
"type": "pickString",
"description": "Select target architecture",
"options": ["x64", "arm64"],
"default": "x64"
}
],
"configurations": [
{
"name": "Run native executable (no build)",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}\\${input:arch}\\Debug\\PowerToys.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"console": "integratedTerminal"
},
{
"name": "C/C++ Attach to PowerToys Process (native)",
"type": "cppvsdbg",
"request": "attach",
"processId": "${command:pickProcess}",
"symbolSearchPath": "${workspaceFolder}\\${input:arch}\\Debug;${workspaceFolder}\\Debug;${workspaceFolder}\\symbols"
},
{
"name": "Run managed code (managed, no build, ARCH configurable)",
"type": "coreclr",
"request": "launch",
"program": "${workspaceFolder}\\${input:arch}\\Debug\\WinUI3Apps\\PowerToys.Settings.exe",
"args": [],
"cwd": "${workspaceFolder}",
"env": {},
"console": "internalConsole",
"stopAtEntry": false
}
]
}

View File

@@ -21,8 +21,7 @@
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.Markdown" Version="7.1.2" />
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" Version="0.1.250703-build.2173" />
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" Version="0.1.250910-build.2249" />
<PackageVersion Include="ControlzEx" Version="6.0.0" />
<PackageVersion Include="HelixToolkit" Version="2.24.0" />
<PackageVersion Include="HelixToolkit.Core.Wpf" Version="2.24.0" />

View File

@@ -1509,7 +1509,6 @@ SOFTWARE.
- CommunityToolkit.WinUI.Converters
- CommunityToolkit.WinUI.Extensions
- CommunityToolkit.WinUI.UI.Controls.DataGrid
- CommunityToolkit.WinUI.UI.Controls.Markdown
- ControlzEx
- HelixToolkit
- HelixToolkit.Core.Wpf

View File

@@ -2932,7 +2932,6 @@ Global
{D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9} = {264B412F-DB8B-4CF8-A74B-96998B183045}
{1AFB6476-670D-4E80-A464-657E01DFF482} = {557C4636-D7E1-4838-A504-7D19B725EE95}
{1A066C63-64B3-45F8-92FE-664E1CCE8077} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}

View File

@@ -0,0 +1,128 @@
## Developing PowerToys with Visual Studio Code
This guide shows how to build, debug, and contribute to PowerToys using VS Code instead of (or alongside) full Visual Studio. It focuses on common innerloop tasks for C++, .NET, and mixed scenarios present in the solution.
> PowerToys is a large mixed C++ / C# / WinAppSDK solution. VS Code works well for incremental development and quick module iterations, but occasionally you may still prefer full Visual Studio for designer tooling or specialized diagnostics.
---
VS Code extensions Needed:
| Area | Extension | Notes |
|------|-----------|-------|
| C++ | ms-vscode.cpptools | IntelliSense, debugging (cppvsdbg) |
| C# | ms-dotnettools.csdevkit (or C#) | Language service / test explorer |
---
## Building in VS Code
### Configure developer powershell for vs2022 for more convenient dev in vscode.
1. Configure profile in in settings, entry: "terminal.integrated.profiles.windows"
2. Add below config as entry:
```json
"Developer PowerShell for VS 2022": {
// Configure based on your preference
"path": "C:\\Program Files\\WindowsApps\\Microsoft.PowerShell_7.5.2.0_arm64__8wekyb3d8bbwe\\pwsh.exe",
"args": [
"-NoExit",
"-Command",
"& {",
"$orig = Get-Location;",
// Configure based on your environment
"& 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Common7\\Tools\\Launch-VsDevShell.ps1';",
"Set-Location $orig",
"}"
]
},
```
3. [Optional] Set Developer PowerShell for VS 2022 as your default profile, so that you can get a deep integration with vscode coding agent.
4. Now You can build with plain `msbuild` or configure tasks.json in below section
Or reach out to "tools\build\BUILD-GUIDELINES.md"
### Sample plain msbuild command
```powershell
# Restore:
msbuild powertoys.sln -t:restore -p:configuration=debug -p:platform=x64 -m
# Build powertoys sln
msbuild powertoys.sln -p:configuration=debug -p:platform=x64 -m
# dotnet project
msbuild src\settings-ui\Settings.UI\PowerToys.Settings.csproj -p:Platform=x64 -p:Configuration=Debug -m
# native project
msbuild "src\modules\MouseUtils\FindMyMouse\FindMyMouse.vcxproj" -p:Configuration=Debug -p:Platform=x64 -m
```
---
## Debugging
### Existing launch configuration
The repo provides `.vscode/launch.json` with:
- `Run PowerToys.exe (no build)`: Launches the already-built executable at `x64/Debug/PowerToys.exe` using `cppvsdbg`.
Build first, then press F5. To switch configuration (Release / ARM64) either edit the path or create additional launch entries.
### Attaching to a running instance
If PowerToys is already running, you can attach to that process:
2. VS Code command palette: “C/C++: (Windows) Attach to Process”.
3. Filter for `PowerToys.exe` / module-specific processes.
### Debugging managed components
Many modules have a managed component loaded into the PowerToys process. `cppvsdbg` can debug mixed mode, but if you need richer .NET inspection you can create a second configuration using `type: coreclr` and `processId` attachment after the native launch, or just attach separately:
Similar for attach to managed code.
> Note: In arm64 machine, can only debug arm64 code.
```jsonc
{
"version": "0.2.0",
"configurations": [
{
"name": "Run native executable (no build)",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}\\x64\\Debug\\PowerToys.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"console": "integratedTerminal"
},
{
"name": "C/C++ Attach to PowerToys Process (native)",
"type": "cppvsdbg",
"request": "attach",
"processId": "${command:pickProcess}",
"symbolSearchPath": "${workspaceFolder}\\x64\\Debug;${workspaceFolder}\\Debug;${workspaceFolder}\\symbols"
},
{
"name": "Run managed code (managed, no build)",
"type": "coreclr",
"request": "launch",
"program": "${workspaceFolder}\\arm64\\Debug\\WinUI3Apps\\PowerToys.Settings.exe",
"args": [],
"cwd": "${workspaceFolder}",
"env": {},
"console": "internalConsole",
"stopAtEntry": false
}
]
}
```
---
## 6. Common tasks & tips
| Task | Command / Action | Notes |
|------|------------------|-------|
| Clean | `git clean -xdf` (careful) or `msbuild /t:Clean PowerToys.sln` | Deep clean removes packages & build outputs |
| Rebuild single project | `msbuild path\to\proj.vcxproj /t:Rebuild -p:Platform=x64 -p:Configuration=Debug` | Faster than whole solution |
| Generate installer (rare in inner loop) | See `tools\build\build-installer.ps1` | Usually not needed for local debug |
| Resource conversion errors | Re-run restore + build | Triggers custom PowerShell targets |

View File

@@ -49,23 +49,23 @@ namespace MouseUtils.UITests
settings.BackgroundColor = "000000";
settings.SpotlightColor = "FFFFFF";
var foundCustom = this.Find<Custom>("Find My Mouse");
var foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
Assert.IsNotNull(foundCustom);
if (CheckAnimationEnable(ref foundCustom))
{
foundCustom = this.Find<Custom>("Find My Mouse");
foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
}
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom, "Find My Mouse group not found.");
SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
var excludedApps = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseExcludedApps));
if (excludedApps != null)
{
excludedApps.Click();
@@ -115,23 +115,23 @@ namespace MouseUtils.UITests
settings.BackgroundColor = "FF0000";
settings.SpotlightColor = "0000FF";
var foundCustom = this.Find<Custom>("Find My Mouse");
var foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
Assert.IsNotNull(foundCustom);
if (CheckAnimationEnable(ref foundCustom))
{
foundCustom = this.Find<Custom>("Find My Mouse");
foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
}
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom, "Find My Mouse group not found.");
SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
var excludedApps = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseExcludedApps));
if (excludedApps != null)
{
excludedApps.Click();
@@ -170,27 +170,27 @@ namespace MouseUtils.UITests
settings.AnimationDuration = "0";
settings.BackgroundColor = "000000";
settings.SpotlightColor = "FFFFFF";
var foundCustom = this.Find<Custom>("Find My Mouse");
var foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
Assert.IsNotNull(foundCustom);
if (CheckAnimationEnable(ref foundCustom))
{
foundCustom = this.Find<Custom>("Find My Mouse");
foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
}
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom);
SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
var excludedApps = foundCustom.Find<Group>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseExcludedApps));
if (excludedApps != null)
{
excludedApps.Click();
@@ -212,14 +212,14 @@ namespace MouseUtils.UITests
VerifySpotlightAppears(ref settings);
// [Test Case] Disable FindMyMouse. Verify the overlay no longer appears when you press Left Ctrl twice
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
Task.Delay(1000).Wait();
ActivateSpotlight(ref settings);
VerifySpotlightDisappears(ref settings);
// [Test Case] Press Left Ctrl twice and verify the overlay appears
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
Task.Delay(2000).Wait();
ActivateSpotlight(ref settings);
VerifySpotlightAppears(ref settings);
@@ -240,27 +240,27 @@ namespace MouseUtils.UITests
settings.AnimationDuration = "0";
settings.BackgroundColor = "000000";
settings.SpotlightColor = "FFFFFF";
var foundCustom = this.Find<Custom>("Find My Mouse");
var foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
Assert.IsNotNull(foundCustom);
if (CheckAnimationEnable(ref foundCustom))
{
foundCustom = this.Find<Custom>("Find My Mouse");
foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
}
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom);
SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
var excludedApps = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseExcludedApps));
if (excludedApps != null)
{
excludedApps.Click();
@@ -282,14 +282,14 @@ namespace MouseUtils.UITests
VerifySpotlightAppears(ref settings);
// [Test Case] Disable FindMyMouse. Verify the overlay no longer appears when you press Left Ctrl twice
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
Task.Delay(1000).Wait();
ActivateSpotlight(ref settings);
VerifySpotlightDisappears(ref settings);
// [Test Case] Press Left Ctrl twice and verify the overlay appears
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
Task.Delay(2000).Wait();
ActivateSpotlight(ref settings);
VerifySpotlightAppears(ref settings);
@@ -310,17 +310,17 @@ namespace MouseUtils.UITests
settings.AnimationDuration = "0";
settings.BackgroundColor = "000000";
settings.SpotlightColor = "FFFFFF";
var foundCustom = this.Find<Custom>("Find My Mouse");
var foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
// foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
// foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
SetFindMyMouseActivationMethod(ref foundCustom, "Press Left Control twice");
Assert.IsNotNull(foundCustom, "Find My Mouse group not found.");
// SetFindMyMouseAppearanceBehavior(ref foundCustom, ref settings);
var excludedApps = foundCustom.Find<TextBlock>("Excluded apps");
var excludedApps = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseExcludedApps));
if (excludedApps != null)
{
excludedApps.Click();
@@ -340,7 +340,7 @@ namespace MouseUtils.UITests
// VerifySpotlightSettings(ref settings);
// [Test Case] Disable FindMyMouse. Verify the overlay no longer appears when you press Left Ctrl twice
foundCustom.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
Task.Delay(2000).Wait();
Session.SendKey(Key.LCtrl, 0, 0);
Task.Delay(100).Wait();
@@ -382,9 +382,6 @@ namespace MouseUtils.UITests
var colorBackground = this.GetPixelColorString(location.Item1 + radius + 50, location.Item2 + radius + 50);
Assert.AreEqual("#" + settings.BackgroundColor, colorBackground);
var colorBackground2 = this.GetPixelColorString(location.Item1 + radius + 100, location.Item2 + radius + 100);
Assert.AreEqual("#" + settings.BackgroundColor, colorBackground2);
}
private void ActivateSpotlight(ref FindMyMouseSettings settings)
@@ -427,7 +424,7 @@ namespace MouseUtils.UITests
private void SetFindMyMouseActivationMethod(ref Custom? foundCustom, string method)
{
Assert.IsNotNull(foundCustom);
var groupActivation = foundCustom.Find<TextBlock>("Activation method");
var groupActivation = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseActivationMethod));
if (groupActivation != null)
{
groupActivation.Click();
@@ -456,17 +453,17 @@ namespace MouseUtils.UITests
private void SetFindMyMouseAppearanceBehavior(ref Custom foundCustom, ref FindMyMouseSettings settings)
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
var groupAppearanceBehavior = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseAppearanceBehavior));
if (groupAppearanceBehavior != null)
{
// groupAppearanceBehavior.Click();
if (foundCustom.FindAll<Slider>("Overlay opacity (%)").Count == 0)
if (foundCustom.FindAll(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseOverlayOpacity)).Count == 0)
{
groupAppearanceBehavior.Click();
}
// Set the BackGround color
var backgroundColor = foundCustom.Find<Group>("Background color");
var backgroundColor = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseBackgroundColor));
Assert.IsNotNull(backgroundColor);
var button = backgroundColor.Find<Button>(By.XPath(".//Button"));
@@ -505,7 +502,7 @@ namespace MouseUtils.UITests
button.Click();
// Set the Spotlight color
var spotlightColor = foundCustom.Find<Group>("Spotlight color");
var spotlightColor = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseSpotlightColor));
Assert.IsNotNull(spotlightColor);
var spotlightColorButton = spotlightColor.Find<Button>(By.XPath(".//Button"));
@@ -545,7 +542,7 @@ namespace MouseUtils.UITests
spotlightColorButton.Click(false, 500, 1500);
// Set the overlay opacity to overlayOpacity%
var overlayOpacitySlider = foundCustom.Find<Slider>("Overlay opacity (%)");
var overlayOpacitySlider = foundCustom.Find<Slider>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseOverlayOpacity));
Assert.IsNotNull(overlayOpacitySlider);
Assert.IsNotNull(settings.OverlayOpacity);
int overlayOpacityValue = int.Parse(settings.OverlayOpacity, CultureInfo.InvariantCulture);
@@ -554,7 +551,7 @@ namespace MouseUtils.UITests
Task.Delay(1000).Wait();
// Set the Fade Initial zoom to 0
var spotlightInitialZoomSlider = foundCustom.Find<Slider>("Spotlight initial zoom");
var spotlightInitialZoomSlider = foundCustom.Find<Slider>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseSpotlightZoom));
Assert.IsNotNull(spotlightInitialZoomSlider);
Task.Delay(1000).Wait();
spotlightInitialZoomSlider.QuickSetValue(int.Parse(settings.InitialZoom, CultureInfo.InvariantCulture));
@@ -562,7 +559,8 @@ namespace MouseUtils.UITests
Task.Delay(1000).Wait();
//// Change the edit value
var spotlightRadiusEdit = foundCustom.Find<TextBox>("Spotlight radius (px) Minimum5");
var spotlightRadius = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseSpotlightRadius));
var spotlightRadiusEdit = spotlightRadius.Find<TextBox>(By.AccessibilityId("InputBox"));
Assert.IsNotNull(spotlightRadiusEdit);
Task.Delay(1000).Wait();
spotlightRadiusEdit.SetText(settings.Radius);
@@ -570,11 +568,12 @@ namespace MouseUtils.UITests
Task.Delay(1000).Wait();
// Set the duration to 0 ms
var spotlightAnimationDuration = foundCustom.Find<TextBox>("Animation duration (ms) Minimum0");
Assert.IsNotNull(spotlightAnimationDuration);
var spotlightAnimationDuration = foundCustom.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseAnimationDuration));
var spotlightAnimationDurationEdit = spotlightAnimationDuration.Find<TextBox>(By.AccessibilityId("InputBox"));
Assert.IsNotNull(spotlightAnimationDurationEdit);
Task.Delay(1000).Wait();
spotlightAnimationDuration.SetText(settings.AnimationDuration);
Assert.AreEqual(settings.AnimationDuration, spotlightAnimationDuration.Text);
spotlightAnimationDurationEdit.SetText(settings.AnimationDuration);
Assert.AreEqual(settings.AnimationDuration, spotlightAnimationDurationEdit.Text);
Task.Delay(1000).Wait();
// groupAppearanceBehavior.Click();
@@ -622,19 +621,19 @@ namespace MouseUtils.UITests
this.Session.SetMainWindowSize(WindowSize.Large);
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities", 10000).Count == 0)
if (this.FindAll(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseUtilitiesNavItem)).Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").Click();
this.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.InputOutputNavItem)).Click();
}
if (reload)
{
this.Find<NavigationViewItem>("Keyboard Manager").Click();
this.Find<NavigationViewItem>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.KeyboardManagerNavItem)).Click();
}
Task.Delay(1000).Wait();
this.Find<NavigationViewItem>("Mouse utilities").Click();
this.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseUtilitiesNavItem)).Click();
}
}
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -24,10 +24,10 @@ namespace MouseUtils.UITests
public void TestEnableMouseHighlighter()
{
LaunchFromSetting();
var foundCustom0 = this.Find<Custom>("Find My Mouse");
var foundCustom0 = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
if (foundCustom0 != null)
{
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom0.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
}
else
{
@@ -42,11 +42,11 @@ namespace MouseUtils.UITests
settings.FadeDelay = "0";
settings.FadeDuration = "90";
var foundCustom = this.Find<Custom>("Mouse Highlighter");
var foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighter));
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(false);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterToggle)).Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterToggle)).Toggle(false);
var xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1, xy.Item2 - 100);
@@ -54,7 +54,7 @@ namespace MouseUtils.UITests
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterToggle)).Toggle(true);
// Change the shortcut key for MouseHighlighter
// [TestCase]Change activation shortcut and test it
@@ -107,7 +107,7 @@ namespace MouseUtils.UITests
VerifyMouseHighlighterNotAppears(ref settings, "rightClick");
// [Test Case] Disable Mouse Highlighter and verify that the module is not activated when you press the activation shortcut.
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(false);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterToggle)).Toggle(false);
xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1 - 100, xy.Item2);
@@ -119,7 +119,7 @@ namespace MouseUtils.UITests
// [Test Case] With left mouse button pressed, drag the mouse and verify the highlight is dragged with the pointer.
// [Test Case] With right mouse button pressed, drag the mouse and verify the highlight is dragged with the pointer.
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterToggle)).Toggle(true);
xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1 - 100, xy.Item2);
@@ -143,10 +143,10 @@ namespace MouseUtils.UITests
public void TestMouseHighlighterDifferentSettings()
{
LaunchFromSetting();
var foundCustom0 = this.Find<Custom>("Find My Mouse");
var foundCustom0 = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
if (foundCustom0 != null)
{
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom0.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
}
else
{
@@ -161,11 +161,11 @@ namespace MouseUtils.UITests
settings.FadeDelay = "0";
settings.FadeDuration = "90";
var foundCustom = this.Find<Custom>("Mouse Highlighter");
var foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighter));
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(false);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterToggle)).Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterToggle)).Toggle(false);
var xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1, xy.Item2 - 100);
@@ -173,7 +173,7 @@ namespace MouseUtils.UITests
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
Session.PerformMouseAction(MouseActionType.ScrollDown);
foundCustom.Find<ToggleSwitch>("Enable Mouse Highlighter").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterToggle)).Toggle(true);
// Change the shortcut key for MouseHighlighter
// [TestCase] Test the different settings and verify they apply - Change activation shortcut and test it
@@ -387,7 +387,7 @@ namespace MouseUtils.UITests
private void SetColor(ref Custom foundCustom, string colorName = "Primary button highlight color", string colorValue = "000000", string opacity = "0")
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
var groupAppearanceBehavior = foundCustom.Find<Group>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterAppearanceBehavior));
if (groupAppearanceBehavior != null)
{
if (foundCustom.FindAll<TextBox>("Fade duration (ms) Minimum0").Count == 0)
@@ -439,7 +439,7 @@ namespace MouseUtils.UITests
private void SetMouseHighlighterAppearanceBehavior(ref Custom foundCustom, ref MouseHighlighterSettings settings)
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
var groupAppearanceBehavior = foundCustom.Find<Group>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseHighlighterAppearanceBehavior));
if (groupAppearanceBehavior != null)
{
// groupAppearanceBehavior.Click();
@@ -477,7 +477,7 @@ namespace MouseUtils.UITests
}
else
{
Assert.Fail("Appearance & behavior group not found.");
Assert.Fail("MouseHighlighter Appearance & behavior group not found.");
}
}
@@ -485,14 +485,14 @@ namespace MouseUtils.UITests
{
this.Session.SetMainWindowSize(WindowSize.Large);
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities").Count == 0)
// Goto Mouse utilities setting page
if (this.FindAll(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseUtilitiesNavItem)).Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").Click();
// Expand Input / Output list-group if needed
this.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.InputOutputNavItem)).Click();
}
this.Find<NavigationViewItem>("Mouse utilities").Click();
this.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseUtilitiesNavItem)).Click();
}
}
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -29,11 +29,11 @@ namespace MouseUtils.UITests
public void TestEnableMouseJump2()
{
LaunchFromSetting();
var foundCustom0 = this.Find<Custom>("Find My Mouse");
var foundCustom0 = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
if (foundCustom0 != null)
{
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom0.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
foundCustom0.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
}
else
{
@@ -45,10 +45,10 @@ namespace MouseUtils.UITests
Session.PerformMouseAction(MouseActionType.ScrollDown);
}
var foundCustom = this.Find<Custom>("Mouse Jump");
var foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseJump));
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Mouse Jump").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseJumpToggle)).Toggle(true);
var xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1, xy.Item2 - 100);
@@ -89,7 +89,7 @@ namespace MouseUtils.UITests
Task.Delay(1000).Wait();
// [TestCase] Enable Mouse Jump. Then - Disable Mouse Jump and verify that the module is not activated when you press the activation shortcut.
foundCustom.Find<ToggleSwitch>("Enable Mouse Jump").Toggle(false);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseJumpToggle)).Toggle(false);
Session.MoveMouseTo(screenCenter.CenterX, screenCenter.CenterY - 300, 500, 1000);
Session.SendKeys(Key.Win, Key.Shift, Key.Z);
Task.Delay(500).Wait();
@@ -108,11 +108,11 @@ namespace MouseUtils.UITests
public void TestEnableMouseJump3()
{
LaunchFromSetting();
var foundCustom0 = this.Find<Custom>("Find My Mouse");
var foundCustom0 = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouse));
if (foundCustom0 != null)
{
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(true);
foundCustom0.Find<ToggleSwitch>("Enable Find My Mouse").Toggle(false);
foundCustom0.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(true);
foundCustom0.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.FindMyMouseToggle)).Toggle(false);
}
else
{
@@ -124,10 +124,10 @@ namespace MouseUtils.UITests
Session.PerformMouseAction(MouseActionType.ScrollDown);
}
var foundCustom = this.Find<Custom>("Mouse Jump");
var foundCustom = this.Find<Custom>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseJump));
if (foundCustom != null)
{
foundCustom.Find<ToggleSwitch>("Enable Mouse Jump").Toggle(true);
foundCustom.Find<ToggleSwitch>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseJumpToggle)).Toggle(true);
var xy = Session.GetMousePosition();
Session.MoveMouseTo(xy.Item1, xy.Item2 - 100);
@@ -215,23 +215,23 @@ namespace MouseUtils.UITests
Session.SetMainWindowSize(WindowSize.Large);
Task.Delay(1000).Wait();
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities").Count == 0)
// Goto Mouse utilities setting page
if (this.FindAll(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseUtilitiesNavItem)).Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").ClickCenter();
// Expand Input / Output list-group if needed
this.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.InputOutputNavItem)).Click();
Task.Delay(2000).Wait();
}
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities").Count == 0)
// Goto Mouse utilities setting page
if (this.FindAll(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseUtilitiesNavItem)).Count == 0)
{
RestartScopeExe();
Session.SetMainWindowSize(WindowSize.Large);
Task.Delay(1000).Wait();
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").ClickCenter();
// Expand Input / Output list-group if needed
this.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.InputOutputNavItem)).Click();
Task.Delay(2000).Wait();
}
@@ -243,7 +243,7 @@ namespace MouseUtils.UITests
}
else
{
this.Find<NavigationViewItem>("Mouse utilities").Click();
this.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseUtilitiesNavItem)).Click();
}
}
}

View File

@@ -249,7 +249,7 @@ namespace MouseUtils.UITests
private void SetColor(ref Custom foundCustom, string colorName, string colorValue = "000000")
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
var groupAppearanceBehavior = foundCustom.Find<Group>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MousePointerCrosshairsAppearanceBehavior));
if (groupAppearanceBehavior != null)
{
// Set primary button highlight color
@@ -277,7 +277,7 @@ namespace MouseUtils.UITests
private void SetMousePointerCrosshairsAppearanceBehavior(ref Custom foundCustom, ref MousePointerCrosshairsSettings settings)
{
Assert.IsNotNull(foundCustom);
var groupAppearanceBehavior = foundCustom.Find<TextBlock>("Appearance & behavior");
var groupAppearanceBehavior = foundCustom.Find<Group>(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MousePointerCrosshairsAppearanceBehavior));
if (groupAppearanceBehavior != null)
{
// groupAppearanceBehavior.Click();
@@ -337,7 +337,7 @@ namespace MouseUtils.UITests
}
else
{
Assert.Fail("Appearance & behavior group not found.");
Assert.Fail("MousePointerCrosshairs Appearance & behavior group not found.");
}
}
@@ -371,8 +371,16 @@ namespace MouseUtils.UITests
public Custom? FindMouseUtilElement(MouseUtilsSettings.MouseUtils element)
{
var elementName = MouseUtilsSettings.GetMouseUtilUIName(element);
var foundCustom = this.Find<Custom>(elementName);
string accessibilityId = element switch
{
MouseUtilsSettings.MouseUtils.FindMyMouse => MouseUtilsSettings.AccessibilityIds.FindMyMouse,
MouseUtilsSettings.MouseUtils.MouseHighlighter => MouseUtilsSettings.AccessibilityIds.MouseHighlighter,
MouseUtilsSettings.MouseUtils.MousePointerCrosshairs => MouseUtilsSettings.AccessibilityIds.MousePointerCrosshairs,
MouseUtilsSettings.MouseUtils.MouseJump => MouseUtilsSettings.AccessibilityIds.MouseJump,
_ => throw new ArgumentException($"Unknown MouseUtils element: {element}"),
};
var foundCustom = this.Find<Custom>(By.AccessibilityId(accessibilityId));
for (int i = 0; i < 20; i++)
{
if (foundCustom != null)
@@ -381,7 +389,7 @@ namespace MouseUtils.UITests
}
Session.PerformMouseAction(MouseActionType.ScrollDown);
foundCustom = this.Find<Custom>(elementName);
foundCustom = this.Find<Custom>(By.AccessibilityId(accessibilityId));
}
return foundCustom;
@@ -391,14 +399,14 @@ namespace MouseUtils.UITests
{
Session.SetMainWindowSize(WindowSize.Large);
// Goto Hosts File Editor setting page
if (this.FindAll<NavigationViewItem>("Mouse utilities").Count == 0)
// Goto Mouse utilities setting page
if (this.FindAll(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseUtilitiesNavItem)).Count == 0)
{
// Expand Advanced list-group if needed
this.Find<NavigationViewItem>("Input / Output").Click();
// Expand Input / Output list-group if needed
this.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.InputOutputNavItem)).Click();
}
this.Find<NavigationViewItem>("Mouse utilities").Click();
this.Find(By.AccessibilityId(MouseUtilsSettings.AccessibilityIds.MouseUtilitiesNavItem)).Click();
}
}
}

View File

@@ -11,6 +11,48 @@ namespace MouseUtils.UITests
{
public class MouseUtilsSettings
{
// Accessibility ID constants
public static class AccessibilityIds
{
// Mouse Utils module IDs
public const string FindMyMouse = "MouseUtils_FindMyMouseTestId";
public const string MouseHighlighter = "MouseUtils_MouseHighlighterTestId";
public const string MousePointerCrosshairs = "MouseUtils_MousePointerCrosshairsTestId";
public const string MouseJump = "MouseUtils_MouseJumpTestId";
// ToggleSwitch IDs
public const string FindMyMouseToggle = "MouseUtils_FindMyMouseToggleId";
public const string MouseHighlighterToggle = "MouseUtils_MouseHighlighterToggleId";
public const string MousePointerCrosshairsToggle = "MouseUtils_MousePointerCrosshairsToggleId";
public const string MouseJumpToggle = "MouseUtils_MouseJumpToggleId";
// Find My Mouse UI Element IDs
public const string FindMyMouseActivationMethod = "MouseUtils_FindMyMouseActivationMethodId";
public const string FindMyMouseAppearanceBehavior = "MouseUtils_FindMyMouseAppearanceBehaviorId";
public const string FindMyMouseExcludedApps = "MouseUtils_FindMyMouseExcludedAppsId";
public const string FindMyMouseBackgroundColor = "MouseUtils_FindMyMouseBackgroundColorId";
public const string FindMyMouseSpotlightColor = "MouseUtils_FindMyMouseSpotlightColorId";
public const string FindMyMouseOverlayOpacity = "MouseUtils_FindMyMouseOverlayOpacityId";
public const string FindMyMouseSpotlightZoom = "MouseUtils_FindMyMouseSpotlightZoomId";
public const string FindMyMouseSpotlightRadius = "MouseUtils_FindMyMouseSpotlightRadiusId";
public const string FindMyMouseAnimationDuration = "MouseUtils_FindMyMouseAnimationDurationId";
// Mouse Highlighter UI Element IDs
public const string MouseHighlighterActivationShortcut = "MouseUtils_MouseHighlighterActivationShortcutId";
public const string MouseHighlighterAppearanceBehavior = "MouseUtils_MouseHighlighterAppearanceBehaviorId";
// Mouse Pointer Crosshairs UI Element IDs
public const string MousePointerCrosshairsAppearanceBehavior = "MouseUtils_MousePointerCrosshairsAppearanceBehaviorId";
// Mouse Jump UI Element IDs
public const string MouseJumpActivationShortcut = "MouseUtils_MouseJumpActivationShortcutId";
// Navigation IDs
public const string InputOutputNavItem = "InputOutputNavItem";
public const string MouseUtilitiesNavItem = "MouseUtilitiesNavItem";
public const string KeyboardManagerNavItem = "KeyboardManagerNavItem";
}
// Mouse Utils Modules
public enum MouseUtils
{

View File

@@ -121,8 +121,8 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,166,306,50,14
PUSHBUTTON "Cancel",IDCANCEL,223,306,50,14
LTEXT "ZoomIt v9.0",IDC_VERSION,42,7,73,10
LTEXT "Copyright <EFBFBD> 2006-2024 Mark Russinovich",IDC_COPYRIGHT,42,17,166,8
LTEXT "ZoomIt v9.01",IDC_VERSION,42,7,73,10
LTEXT "Copyright © 2006-2025 Mark Russinovich",IDC_COPYRIGHT,42,17,166,8
CONTROL "<a HREF=""https://www.sysinternals.com"">Sysinternals - www.sysinternals.com</a>",IDC_LINK,
"SysLink",WS_TABSTOP,42,26,150,9
ICON "APPICON",IDC_STATIC,12,9,20,20

View File

@@ -3525,6 +3525,10 @@ winrt::fire_and_forget StartRecordingAsync( HWND hWnd, LPRECT rcCrop, HWND hWndR
}
if( destFile == nullptr ) {
if (stream) {
stream.Close();
stream = nullptr;
}
co_await file.DeleteAsync();
}
else {
@@ -3544,6 +3548,10 @@ winrt::fire_and_forget StartRecordingAsync( HWND hWnd, LPRECT rcCrop, HWND hWndR
}
else {
if (stream) {
stream.Close();
stream = nullptr;
}
co_await file.DeleteAsync();
g_RecordingSession = nullptr;
}
@@ -4016,7 +4024,10 @@ LRESULT APIENTRY MainWndProc(
// Now copy crop or copy+save
if( LOWORD( wParam ) == SNIP_SAVE_HOTKEY )
{
// Hide cursor for screen capture
ShowCursor(false);
SendMessage( hWnd, WM_COMMAND, IDC_SAVE_CROP, ( zoomed ? 0 : SHALLOW_ZOOM ) );
ShowCursor(true);
}
else
{
@@ -4048,12 +4059,6 @@ LRESULT APIENTRY MainWndProc(
OutputDebug( L"Exiting liveDraw after snip\n" );
SendMessage( hWnd, WM_KEYDOWN, VK_ESCAPE, 0 );
}
else
{
// Set wparam to 1 to exit without animation
OutputDebug(L"Exiting zoom after snip\n" );
SendMessage( hWnd, WM_HOTKEY, ZOOM_HOTKEY, SHALLOW_DESTROY );
}
}
break;
}
@@ -5778,17 +5783,26 @@ LRESULT APIENTRY MainWndProc(
if( !g_DrawingShape ) {
Gdiplus::Graphics dstGraphics(hdcScreenCompat);
if( ( GetWindowLong( g_hWndMain, GWL_EXSTYLE ) & WS_EX_LAYERED ) == 0 )
{
dstGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
// If the point has changed, draw a line to it
if (prevPt.x != LOWORD(lParam) || prevPt.y != HIWORD(lParam)) {
Gdiplus::Graphics dstGraphics(hdcScreenCompat);
if ((GetWindowLong(g_hWndMain, GWL_EXSTYLE) & WS_EX_LAYERED) == 0)
{
dstGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
}
Gdiplus::Color color = ColorFromColorRef(g_PenColor);
Gdiplus::Pen pen(color, static_cast<Gdiplus::REAL>(g_PenWidth));
Gdiplus::GraphicsPath path;
pen.SetLineJoin(Gdiplus::LineJoinRound);
path.AddLine(prevPt.x, prevPt.y, LOWORD(lParam), HIWORD(lParam));
dstGraphics.DrawPath(&pen, &path);
}
// Draw a dot at the current point, if the point hasn't changed
else {
MoveToEx(hdcScreenCompat, prevPt.x, prevPt.y, NULL);
LineTo(hdcScreenCompat, LOWORD(lParam), HIWORD(lParam));
InvalidateRect(hWnd, NULL, FALSE);
}
Gdiplus::Color color = ColorFromColorRef(g_PenColor);
Gdiplus::Pen pen(color, static_cast<Gdiplus::REAL>(g_PenWidth));
Gdiplus::GraphicsPath path;
pen.SetLineJoin(Gdiplus::LineJoinRound);
path.AddLine(prevPt.x, prevPt.y, LOWORD(lParam), HIWORD(lParam));
dstGraphics.DrawPath(&pen, &path);
prevPt.x = LOWORD( lParam );
prevPt.y = HIWORD( lParam );

View File

@@ -5,6 +5,7 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using ManagedCommon;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -117,36 +118,46 @@ public partial class ContextMenuViewModel : ObservableObject,
/// Generates a mapping of key -> command item for this particular item's
/// MoreCommands. (This won't include the primary Command, but it will
/// include the secondary one). This map can be used to quickly check if a
/// shortcut key was pressed
/// shortcut key was pressed. In case there are duplicate keybindings, the first
/// one is used and the rest are ignored.
/// </summary>
/// <returns>a dictionary of KeyChord -> Context commands, for all commands
/// that have a shortcut key set.</returns>
public Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
private Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
{
if (CurrentContextMenu is null)
var result = new Dictionary<KeyChord, CommandContextItemViewModel>();
var menu = CurrentContextMenu;
if (menu is null)
{
return [];
return result;
}
return CurrentContextMenu
.OfType<CommandContextItemViewModel>()
.Where(c => c.HasRequestedShortcut)
.ToDictionary(
c => c.RequestedShortcut ?? new KeyChord(0, 0, 0),
c => c);
foreach (var item in menu)
{
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
{
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
var added = result.TryAdd(key, cmd);
if (!added)
{
Logger.LogWarning($"Ignoring duplicate keyboard shortcut {KeyChordHelpers.FormatForDebug(key)} on command '{cmd.Title ?? cmd.Name ?? "(unknown)"}'");
}
}
}
return result;
}
public ContextKeybindingResult? CheckKeybinding(bool ctrl, bool alt, bool shift, bool win, VirtualKey key)
{
var keybindings = Keybindings();
if (keybindings is not null)
// Does the pressed key match any of the keybindings?
var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0);
if (keybindings.TryGetValue(pressedKeyChord, out var item))
{
// Does the pressed key match any of the keybindings?
var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0);
if (keybindings.TryGetValue(pressedKeyChord, out var item))
{
return InvokeCommand(item);
}
return InvokeCommand(item);
}
return null;

View File

@@ -51,6 +51,36 @@ public abstract partial class ExtensionObjectViewModel : ObservableObject
DoOnUiThread(() => OnPropertyChanged(propertyName));
}
protected void UpdateProperty(string propertyName1, string propertyName2)
{
DoOnUiThread(() =>
{
OnPropertyChanged(propertyName1);
OnPropertyChanged(propertyName2);
});
}
protected void UpdateProperty(string propertyName1, string propertyName2, string propertyName3)
{
DoOnUiThread(() =>
{
OnPropertyChanged(propertyName1);
OnPropertyChanged(propertyName2);
OnPropertyChanged(propertyName3);
});
}
protected void UpdateProperty(params string[] propertyNames)
{
DoOnUiThread(() =>
{
foreach (var propertyName in propertyNames)
{
OnPropertyChanged(propertyName);
}
});
}
protected void ShowException(Exception ex, string? extensionHint = null)
{
if (PageContext.TryGetTarget(out var pageContext))

View File

@@ -2,7 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
@@ -10,14 +9,11 @@ namespace Microsoft.CmdPal.Core.ViewModels;
public partial class FiltersViewModel : ExtensionObjectViewModel
{
private readonly ExtensionObject<IFilters> _filtersModel = new(null);
private readonly ExtensionObject<IFilters> _filtersModel;
[ObservableProperty]
public partial string CurrentFilterId { get; set; } = string.Empty;
public string CurrentFilterId { get; private set; } = string.Empty;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(ShouldShowFilters))]
public partial IFilterItemViewModel[] Filters { get; set; } = [];
public IFilterItemViewModel[] Filters { get; private set; } = [];
public bool ShouldShowFilters => Filters.Length > 0;
@@ -34,23 +30,11 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
if (_filtersModel.Unsafe is not null)
{
var filters = _filtersModel.Unsafe.GetFilters();
Filters = filters.Select<IFilterItem, IFilterItemViewModel>(filter =>
{
var filterItem = filter as IFilter;
if (filterItem != null)
{
var filterVM = new FilterItemViewModel(filterItem!, PageContext);
filterVM.InitializeProperties();
Filters = BuildFilters(filters ?? []);
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters));
return filterVM;
}
else
{
return new SeparatorViewModel();
}
}).ToArray();
CurrentFilterId = _filtersModel.Unsafe.CurrentFilterId;
CurrentFilterId = _filtersModel.Unsafe.CurrentFilterId ?? string.Empty;
UpdateProperty(nameof(CurrentFilterId));
return;
}
@@ -61,7 +45,27 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
}
Filters = [];
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters));
CurrentFilterId = string.Empty;
UpdateProperty(nameof(CurrentFilterId));
}
private IFilterItemViewModel[] BuildFilters(IFilterItem[] filters)
{
return [..filters.Select<IFilterItem, IFilterItemViewModel>(filter =>
{
if (filter is IFilter filterItem)
{
var filterItemViewModel = new FilterItemViewModel(filterItem!, PageContext);
filterItemViewModel.InitializeProperties();
return filterItemViewModel;
}
else
{
return new SeparatorViewModel();
}
})];
}
public override void SafeCleanup()
@@ -70,9 +74,9 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
foreach (var filter in Filters)
{
if (filter is FilterItemViewModel filterVM)
if (filter is FilterItemViewModel filterItemViewModel)
{
filterVM.SafeCleanup();
filterItemViewModel.SafeCleanup();
}
}

View File

@@ -3,7 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.ComponentModel;
using ManagedCommon;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
@@ -32,12 +34,28 @@ public interface IContextMenuContext : INotifyPropertyChanged
/// that have a shortcut key set.</returns>
public Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
{
return MoreCommands
.OfType<CommandContextItemViewModel>()
.Where(c => c.HasRequestedShortcut)
.ToDictionary(
c => c.RequestedShortcut ?? new KeyChord(0, 0, 0),
c => c);
var result = new Dictionary<KeyChord, CommandContextItemViewModel>();
var menu = MoreCommands;
if (menu is null)
{
return result;
}
foreach (var item in menu)
{
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
{
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
var added = result.TryAdd(key, cmd);
if (!added)
{
Logger.LogWarning($"Ignoring duplicate keyboard shortcut {KeyChordHelpers.FormatForDebug(key)} on command '{cmd.Title ?? cmd.Name ?? "(unknown)"}'");
}
}
}
return result;
}
}

View File

@@ -59,7 +59,7 @@
<Rectangle
Height="1"
Margin="-16,-12,-12,-12"
Fill="{ThemeResource MenuFlyoutSeparatorThemeBrush}" />
Fill="{ThemeResource MenuFlyoutSeparatorBackground}" />
</DataTemplate>
</ResourceDictionary>
@@ -68,11 +68,14 @@
<ComboBox
Name="FiltersComboBox"
x:Uid="FiltersComboBox"
MinWidth="200"
VerticalAlignment="Center"
ItemTemplateSelector="{StaticResource FilterTemplateSelector}"
ItemsSource="{x:Bind ViewModel.Filters, Mode=OneWay}"
PlaceholderText="Filters"
PreviewKeyDown="FiltersComboBox_PreviewKeyDown"
SelectedValue="{x:Bind ViewModel.CurrentFilterId, Mode=OneWay}"
SelectedValuePath="Id"
SelectionChanged="FiltersComboBox_SelectionChanged"
Style="{StaticResource ComboBoxStyle}"
Visibility="{x:Bind ViewModel.ShouldShowFilters, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">

View File

@@ -131,6 +131,11 @@ public sealed partial class SearchBar : UserControl,
WeakReferenceMessenger.Default.Send<OpenContextMenuMessage>(new OpenContextMenuMessage(null, null, null, ContextMenuFilterLocation.Bottom));
e.Handled = true;
}
else if (ctrlPressed && e.Key == VirtualKey.I)
{
// Today you learned that Ctrl+I in a TextBox will insert a tab
e.Handled = true;
}
else if (e.Key == VirtualKey.Escape)
{
if (string.IsNullOrEmpty(FilterBox.Text))

View File

@@ -4,8 +4,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.CmdPal.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:labToolkit="using:CommunityToolkit.Labs.WinUI.MarkdownTextBlock"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
x:Name="ShortcutContentControl"
mc:Ignorable="d">
<Grid MinWidth="498" MinHeight="220">
@@ -66,7 +66,7 @@
IsTabStop="{Binding ElementName=ShortcutContentControl, Path=IsWarningAltGr, Mode=OneWay}"
Severity="Warning" />
</Grid>
<labToolkit:MarkdownTextBlock
<tkcontrols:MarkdownTextBlock
x:Uid="InvalidShortcutWarningLabel"
Background="Transparent"
FontSize="12"

View File

@@ -4,8 +4,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.CmdPal.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:labToolkit="using:CommunityToolkit.Labs.WinUI.MarkdownTextBlock"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
@@ -36,7 +36,7 @@
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<labToolkit:MarkdownTextBlock
<tkcontrols:MarkdownTextBlock
Grid.Column="1"
VerticalAlignment="Center"
Background="Transparent"

View File

@@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics.CodeAnalysis;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
@@ -14,6 +15,7 @@ internal sealed partial class FilterTemplateSelector : DataTemplateSelector
public DataTemplate? Separator { get; set; }
[DynamicDependency(DynamicallyAccessedMemberTypes.All, "Microsoft.UI.Xaml.Controls.ComboBoxItem", "Microsoft.WinUI")]
protected override DataTemplate? SelectTemplateCore(object item, DependencyObject dependencyObject)
{
DataTemplate? dataTemplate = Default;

View File

@@ -11,22 +11,20 @@
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:coreViewModels="using:Microsoft.CmdPal.Core.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:labToolkit="using:CommunityToolkit.Labs.WinUI.MarkdownTextBlock"
xmlns:local="using:Microsoft.CmdPal.UI"
xmlns:markdownTextBlockRns="using:CommunityToolkit.WinUI.Controls.MarkdownTextBlockRns"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
Background="Transparent"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<markdownTextBlockRns:MarkdownThemes
<tkcontrols:MarkdownThemes
x:Key="DefaultMarkdownThemeConfig"
H3FontSize="12"
H3FontWeight="Normal" />
<labToolkit:MarkdownConfig x:Key="DefaultMarkdownConfig" Themes="{StaticResource DefaultMarkdownThemeConfig}" />
<tkcontrols:MarkdownConfig x:Key="DefaultMarkdownConfig" Themes="{StaticResource DefaultMarkdownThemeConfig}" />
<StackLayout
x:Name="VerticalStackLayout"
@@ -52,10 +50,7 @@
<DataTemplate x:Key="MarkdownContentTemplate" x:DataType="viewModels:ContentMarkdownViewModel">
<Grid Margin="0,4,4,4" Padding="12,8,8,8">
<labToolkit:MarkdownTextBlock
Background="Transparent"
Config="{StaticResource DefaultMarkdownConfig}"
Text="{x:Bind Body, Mode=OneWay}" />
<tkcontrols:MarkdownTextBlock Config="{StaticResource DefaultMarkdownConfig}" Text="{x:Bind Body, Mode=OneWay}" />
</Grid>
</DataTemplate>
@@ -67,10 +62,7 @@
<DataTemplate x:Key="NestedMarkdownContentTemplate" x:DataType="viewModels:ContentMarkdownViewModel">
<Grid>
<labToolkit:MarkdownTextBlock
Background="Transparent"
Config="{StaticResource DefaultMarkdownConfig}"
Text="{x:Bind Body, Mode=OneWay}" />
<tkcontrols:MarkdownTextBlock Config="{StaticResource DefaultMarkdownConfig}" Text="{x:Bind Body, Mode=OneWay}" />
</Grid>
</DataTemplate>

View File

@@ -306,6 +306,36 @@
</controls:Case>
</controls:SwitchPresenter>
</controls:Case>
<controls:Case Value="True">
<StackPanel
Margin="24"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Vertical"
Spacing="4">
<cpcontrols:IconBox
x:Name="IconBorder"
Width="48"
Height="48"
Margin="8"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
SourceKey="{x:Bind ViewModel.EmptyContent.Icon, Mode=OneWay}"
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}" />
<TextBlock
Margin="0,4,0,0"
HorizontalAlignment="Center"
FontWeight="SemiBold"
Text="{x:Bind ViewModel.EmptyContent.Title, Mode=OneWay}"
TextAlignment="Center"
TextWrapping="Wrap" />
<TextBlock
HorizontalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ViewModel.EmptyContent.Subtitle, Mode=OneWay}"
TextAlignment="Center"
TextWrapping="Wrap" />
</StackPanel>
</controls:Case>
</controls:SwitchPresenter>
</Grid>
</Page>

View File

@@ -10,9 +10,8 @@
xmlns:cpcontrols="using:Microsoft.CmdPal.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:help="using:Microsoft.CmdPal.UI.Helpers"
xmlns:labToolkit="using:CommunityToolkit.Labs.WinUI.MarkdownTextBlock"
xmlns:markdownTextBlockRns="using:CommunityToolkit.WinUI.Controls.MarkdownTextBlockRns"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:toolkit="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
@@ -147,11 +146,11 @@
</ItemsControl>
</StackPanel>
</DataTemplate>
<markdownTextBlockRns:MarkdownThemes
<tkcontrols:MarkdownThemes
x:Key="DefaultMarkdownThemeConfig"
H3FontSize="12"
H3FontWeight="Normal" />
<labToolkit:MarkdownConfig x:Key="DefaultMarkdownConfig" Themes="{StaticResource DefaultMarkdownThemeConfig}" />
<tkcontrols:MarkdownConfig x:Key="DefaultMarkdownConfig" Themes="{StaticResource DefaultMarkdownThemeConfig}" />
</ResourceDictionary>
</Page.Resources>
@@ -327,11 +326,6 @@
x:Name="FiltersDropDown"
HorizontalAlignment="Right"
CurrentPageViewModel="{x:Bind ViewModel.CurrentPage, Mode=OneWay}" />
<Grid.Transitions>
<TransitionCollection>
<RepositionThemeTransition />
</TransitionCollection>
</Grid.Transitions>
</Grid>
</Grid>
@@ -427,7 +421,7 @@
TextWrapping="WrapWholeWords"
Visibility="{x:Bind ViewModel.Details.Title, Converter={StaticResource StringNotEmptyToVisibilityConverter}, Mode=OneWay}" />
<labToolkit:MarkdownTextBlock
<tkcontrols:MarkdownTextBlock
Grid.Row="2"
Margin="0,4,0,24"
Background="Transparent"

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -88,11 +88,11 @@ public static class ServiceHelper
];
}
IconInfo icon = Icons.GreenCircleIcon;
IconInfo icon = Icons.PlayIcon;
switch (s.Status)
{
case ServiceControllerStatus.Stopped:
icon = Icons.RedCircleIcon;
icon = Icons.StopIcon;
break;
case ServiceControllerStatus.Running:
break;

View File

@@ -10,17 +10,13 @@ internal sealed class Icons
{
internal static IconInfo ServicesIcon { get; } = IconHelpers.FromRelativePath("Assets\\Services.svg");
internal static IconInfo StopIcon { get; } = new IconInfo("\xE71A"); // Stop icon
internal static IconInfo StopIcon { get; } = IconHelpers.FromRelativePath("Assets\\service_stopped.png");
internal static IconInfo PlayIcon { get; } = new IconInfo("\xEDB5"); // PlayBadge12 icon
internal static IconInfo PlayIcon { get; } = IconHelpers.FromRelativePath("Assets\\service_running.png");
internal static IconInfo RefreshIcon { get; } = new IconInfo("\xE72C"); // Refresh icon
internal static IconInfo OpenIcon { get; } = new IconInfo("\xE8A7"); // OpenInNewWindow icon
internal static IconInfo GreenCircleIcon { get; } = new("\U0001f7e2"); // unicode LARGE GREEN CIRCLE
internal static IconInfo RedCircleIcon { get; } = new("\U0001F534"); // unicode LARGE RED CIRCLE
internal static IconInfo PauseIcon { get; } = new("\u23F8"); // unicode DOUBLE VERTICAL BAR, aka, "Pause"
internal static IconInfo PauseIcon { get; } = IconHelpers.FromRelativePath("Assets\\service_paused.png");
}

View File

@@ -35,6 +35,15 @@
<Content Update="Assets\Services.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="Assets\service_paused.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="Assets\service_running.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="Assets\service_stopped.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">

View File

@@ -18,8 +18,8 @@ public partial class ServiceFilters : Filters
return [
new Filter() { Id = "all", Name = "All Services" },
new Separator(),
new Filter() { Id = "running", Name = "Running", Icon = Icons.GreenCircleIcon },
new Filter() { Id = "stopped", Name = "Stopped", Icon = Icons.RedCircleIcon },
new Filter() { Id = "running", Name = "Running", Icon = Icons.PlayIcon },
new Filter() { Id = "stopped", Name = "Stopped", Icon = Icons.StopIcon },
new Filter() { Id = "paused", Name = "Paused", Icon = Icons.PauseIcon },
];
}

View File

@@ -219,7 +219,12 @@ public partial class EvilSamplesPage : ListPage
}
],
},
new ListItem(new EvilDuplicateRequestedShortcut())
{
Title = "Evil keyboard shortcuts",
Subtitle = "Two commands with the same shortcut and more...",
Icon = new IconInfo("\uE765"),
}
];
public EvilSamplesPage()
@@ -414,3 +419,42 @@ internal sealed partial class EvilFastUpdatesPage : DynamicListPage
}
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Sample code")]
internal sealed partial class EvilDuplicateRequestedShortcut : ListPage
{
private readonly IListItem[] _items =
[
new ListItem(new NoOpCommand())
{
Title = "I'm evil!",
Subtitle = "I have multiple commands sharing the same keyboard shortcut",
MoreCommands = [
new CommandContextItem(new AnonymousCommand(() => new ToastStatusMessage("Me too executed").Show())
{
Result = CommandResult.KeepOpen(),
})
{
Title = "Me too",
RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number1),
},
new CommandContextItem(new AnonymousCommand(() => new ToastStatusMessage("Me three executed").Show())
{
Result = CommandResult.KeepOpen(),
})
{
Title = "Me three",
RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number1),
},
],
},
];
public override IListItem[] GetItems() => _items;
public EvilDuplicateRequestedShortcut()
{
Icon = new IconInfo(string.Empty);
Name = "Open";
}
}

View File

@@ -70,7 +70,7 @@ public partial class SampleFilters : Filters
[
new Filter() { Id = "all", Name = "All" },
new Filter() { Id = "mod2", Name = "Every 2nd", Icon = new IconInfo("2") },
new Filter() { Id = "mod3", Name = "Every 3rd", Icon = new IconInfo("3") },
new Filter() { Id = "mod3", Name = "Every 3rd (and long name)", Icon = new IconInfo("3") },
];
}
}

View File

@@ -6,7 +6,7 @@ using Windows.System;
namespace Microsoft.CommandPalette.Extensions.Toolkit;
public partial class KeyChordHelpers
public static partial class KeyChordHelpers
{
public static KeyChord FromModifiers(
bool ctrl = false,
@@ -34,4 +34,28 @@ public partial class KeyChordHelpers
{
return FromModifiers(ctrl, alt, shift, win, (int)vkey, scanCode);
}
public static string FormatForDebug(KeyChord value)
{
var result = string.Empty;
if (value.Modifiers.HasFlag(VirtualKeyModifiers.Control))
{
result += "Ctrl+";
}
if (value.Modifiers.HasFlag(VirtualKeyModifiers.Shift))
{
result += "Shift+";
}
if (value.Modifiers.HasFlag(VirtualKeyModifiers.Menu))
{
result += "Alt+";
}
result += (VirtualKey)value.Vkey;
return result;
}
}

View File

@@ -4,9 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:winuiex="using:WinUIEx"
MinWidth="480"
MinHeight="320"

View File

@@ -181,8 +181,6 @@ namespace Microsoft.PowerToys.Tools.XamlIndexBuilder
// Define namespaces
XNamespace x = "http://schemas.microsoft.com/winfx/2006/xaml";
XNamespace controls = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
XNamespace labs = "using:CommunityToolkit.Labs.WinUI";
XNamespace winui = "using:CommunityToolkit.WinUI.UI.Controls";
// Extract SettingsPageControl elements
var settingsPageElements = doc.Descendants()

View File

@@ -63,7 +63,7 @@
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Markdown" />
<PackageReference Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" />
<PackageReference Include="System.Net.Http" />
<PackageReference Include="System.Private.Uri" />
<PackageReference Include="System.Text.RegularExpressions" />

View File

@@ -9,7 +9,7 @@
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<UserControl.Resources>
<converters:ColorFormatConverter x:Key="ColorFormatConverter" />
@@ -61,7 +61,7 @@
</DataTemplate>
<ItemsPanelTemplate x:Key="ItemPanelTemplate">
<tk7controls:WrapPanel
<tkcontrols:WrapPanel
HorizontalSpacing="20"
Orientation="Horizontal"
VerticalSpacing="4" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
@@ -35,7 +35,7 @@
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<tk7controls:MarkdownTextBlock
<tkcontrols:MarkdownTextBlock
Grid.Column="1"
Margin="8,0,0,0"
VerticalAlignment="Center"

View File

@@ -2,16 +2,48 @@
x:Class="Microsoft.PowerToys.Settings.UI.Controls.SettingsPageControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
xmlns:toolkit="using:CommunityToolkit.WinUI.Controls"
Loaded="UserControl_Loaded"
mc:Ignorable="d">
<UserControl.Resources>
<x:Double x:Key="PageMaxWidth">1000</x:Double>
<x:Double x:Key="PageHeaderMaxWidth">1020</x:Double>
<tkconverters:DoubleToVisibilityConverter
x:Name="doubleToVisibilityConverter"
FalseValue="Collapsed"
GreaterThan="0"
TrueValue="Visible" />
<animations:ImplicitAnimationSet x:Name="ShowTransitions">
<animations:OffsetAnimation
EasingMode="EaseOut"
From="0,24,0"
To="0"
Duration="0:0:0.4" />
<animations:OpacityAnimation
EasingMode="EaseOut"
From="0"
To="1"
Duration="0:0:0.2" />
</animations:ImplicitAnimationSet>
<animations:ImplicitAnimationSet x:Name="HideTransitions">
<animations:OffsetAnimation
EasingMode="EaseOut"
From="0"
To="0,24,0"
Duration="0:0:0.2" />
<animations:OpacityAnimation
EasingMode="EaseOut"
From="1"
To="0"
Duration="0:0:0.1" />
</animations:ImplicitAnimationSet>
<converters:UriToImageSourceConverter x:Key="UriToImageSourceConverter" />
</UserControl.Resources>
<Grid Padding="20,0,0,0" RowSpacing="24">
@@ -33,14 +65,16 @@
Padding="0,0,20,48"
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
RowSpacing="24">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Top panel -->
<Grid MaxWidth="{StaticResource PageMaxWidth}" RowSpacing="16">
<Grid MaxWidth="{StaticResource PageMaxWidth}" ColumnSpacing="16" RowSpacing="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
@@ -48,6 +82,7 @@
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border
MaxWidth="160"
@@ -65,13 +100,12 @@
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ModuleDescription}"
TextWrapping="Wrap" />
<ItemsControl
<ToggleSwitch IsOn="True"/>
<ItemsControl Visibility="Collapsed"
x:Name="PrimaryLinksControl"
Margin="0,8,0,0"
IsTabStop="False"
ItemsSource="{x:Bind PrimaryLinks}"
Visibility="{x:Bind PrimaryLinks.Count, Converter={StaticResource DoubleToVisibilityConverter}}">
ItemsSource="{x:Bind PrimaryLinks}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="controls:PageLink">
<HyperlinkButton NavigateUri="{x:Bind Link}" Style="{StaticResource TextButtonStyle}">
@@ -81,25 +115,81 @@
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<tk7controls:WrapPanel HorizontalSpacing="24" Orientation="Horizontal" />
<tkcontrols:WrapPanel HorizontalSpacing="24" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</Grid>
<!-- Content panel -->
<ContentPresenter
x:Name="ModuleContentPresenter"
<Grid
Grid.Row="1"
MaxWidth="{StaticResource PageMaxWidth}"
Margin="0,12,0,0"
Content="{x:Bind ModuleContent}" />
Margin="0,-48,0,0">
<SelectorBar x:Name="PivotBar">
<SelectorBarItem
IsSelected="True"
Tag="Settings"
Text="Settings" />
<SelectorBarItem Tag="Docs" Text="Documentation" />
</SelectorBar>
</Grid>
<toolkit:SwitchPresenter
Grid.Row="2"
MaxWidth="{StaticResource PageMaxWidth}"
Value="{Binding SelectedItem.Tag, ElementName=PivotBar}">
<toolkit:Case Value="Settings">
<!-- Content panel -->
<ContentPresenter
x:Name="ModuleContentPresenter"
Margin="0,12,0,0"
Content="{x:Bind ModuleContent}" />
</toolkit:Case>
<toolkit:Case Value="Docs">
<Grid
animations:Implicit.HideAnimations="{StaticResource HideTransitions}"
animations:Implicit.ShowAnimations="{StaticResource ShowTransitions}"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="{StaticResource OverlayCornerRadius}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ListView
x:Name="TocList"
Grid.Row="1"
Grid.Column="1"
IsItemClickEnabled="True"
ItemClick="TocList_ItemClick"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock
Margin="{Binding Indent}"
Tag="{Binding Id}"
Text="{Binding Title}"
TextWrapping="WrapWholeWords" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ScrollViewer
x:Name="DocScroll"
VerticalScrollBarVisibility="Auto"
VerticalScrollMode="Auto">
<StackPanel x:Name="DocHost" Orientation="Vertical" />
</ScrollViewer>
</Grid>
</toolkit:Case>
</toolkit:SwitchPresenter>
<!-- Bottom panel -->
<StackPanel
x:Name="SecondaryLinksPanel"
Grid.Row="2"
Grid.Row="3"
MaxWidth="{StaticResource PageMaxWidth}"
AutomationProperties.Name="{x:Bind SecondaryLinksHeader}"
Orientation="Vertical"
@@ -123,7 +213,7 @@
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<tk7controls:WrapPanel HorizontalSpacing="24" Orientation="Horizontal" />
<tkcontrols:WrapPanel HorizontalSpacing="24" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
@@ -142,9 +232,9 @@
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="DescriptionPanel.(Grid.Row)" Value="1" />
<!--<Setter Target="DescriptionPanel.(Grid.Row)" Value="1" />
<Setter Target="DescriptionPanel.(Grid.Column)" Value="0" />
<Setter Target="DescriptionPanel.(Grid.ColumnSpan)" Value="2" />
<Setter Target="DescriptionPanel.(Grid.ColumnSpan)" Value="2" />-->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>

View File

@@ -3,26 +3,56 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CommunityToolkit.WinUI.Controls;
using Markdig;
using Markdig.Syntax;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Media;
using Windows.Foundation;
using Windows.System;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class SettingsPageControl : UserControl
{
private readonly Dictionary<string, FrameworkElement> _anchors = new();
private readonly MarkdownPipeline _pipeline = new MarkdownPipelineBuilder().UsePreciseSourceLocation().Build();
// For section flyouts
private string _fullMarkdown = string.Empty;
private sealed class HeadingInfo
{
#pragma warning disable SA1401 // Fields should be private
public string Id = string.Empty;
public string Title = string.Empty;
public int Level;
public int Start;
public int End;
#pragma warning restore SA1401 // Fields should be private
}
private readonly List<HeadingInfo> _allHeadings = new();
public SettingsPageControl()
{
this.InitializeComponent();
InitializeComponent();
PrimaryLinks = new ObservableCollection<PageLink>();
SecondaryLinks = new ObservableCollection<PageLink>();
}
public string ModuleTitle
{
get { return (string)GetValue(ModuleTitleProperty); }
set { SetValue(ModuleTitleProperty, value); }
get => (string)GetValue(ModuleTitleProperty);
set => SetValue(ModuleTitleProperty, value);
}
public string ModuleDescription
@@ -45,8 +75,8 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
public string SecondaryLinksHeader
{
get { return (string)GetValue(SecondaryLinksHeaderProperty); }
set { SetValue(SecondaryLinksHeaderProperty, value); }
get => (string)GetValue(SecondaryLinksHeaderProperty);
set => SetValue(SecondaryLinksHeaderProperty, value);
}
public ObservableCollection<PageLink> SecondaryLinks
@@ -57,21 +87,471 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
public object ModuleContent
{
get { return (object)GetValue(ModuleContentProperty); }
set { SetValue(ModuleContentProperty, value); }
get => GetValue(ModuleContentProperty);
set => SetValue(ModuleContentProperty, value);
}
public static readonly DependencyProperty ModuleTitleProperty = DependencyProperty.Register(nameof(ModuleTitle), typeof(string), typeof(SettingsPageControl), new PropertyMetadata(defaultValue: null));
public static readonly DependencyProperty ModuleDescriptionProperty = DependencyProperty.Register(nameof(ModuleDescription), typeof(string), typeof(SettingsPageControl), new PropertyMetadata(defaultValue: null));
public static readonly DependencyProperty ModuleImageSourceProperty = DependencyProperty.Register(nameof(ModuleImageSource), typeof(Uri), typeof(SettingsPageControl), new PropertyMetadata(null));
public static readonly DependencyProperty PrimaryLinksProperty = DependencyProperty.Register(nameof(PrimaryLinks), typeof(ObservableCollection<PageLink>), typeof(SettingsPageControl), new PropertyMetadata(new ObservableCollection<PageLink>()));
public static readonly DependencyProperty SecondaryLinksHeaderProperty = DependencyProperty.Register(nameof(SecondaryLinksHeader), typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty SecondaryLinksProperty = DependencyProperty.Register(nameof(SecondaryLinks), typeof(ObservableCollection<PageLink>), typeof(SettingsPageControl), new PropertyMetadata(new ObservableCollection<PageLink>()));
public static readonly DependencyProperty ModuleContentProperty = DependencyProperty.Register(nameof(ModuleContent), typeof(object), typeof(SettingsPageControl), new PropertyMetadata(new Grid()));
public static readonly DependencyProperty ModuleTitleProperty =
DependencyProperty.Register(nameof(ModuleTitle), typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty ModuleDescriptionProperty =
DependencyProperty.Register(nameof(ModuleDescription), typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty ModuleImageSourceProperty =
DependencyProperty.Register(nameof(ModuleImageSource), typeof(Uri), typeof(SettingsPageControl), new PropertyMetadata(null));
public static readonly DependencyProperty PrimaryLinksProperty =
DependencyProperty.Register(nameof(PrimaryLinks), typeof(ObservableCollection<PageLink>), typeof(SettingsPageControl), new PropertyMetadata(new ObservableCollection<PageLink>()));
public static readonly DependencyProperty SecondaryLinksHeaderProperty =
DependencyProperty.Register(nameof(SecondaryLinksHeader), typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty SecondaryLinksProperty =
DependencyProperty.Register(nameof(SecondaryLinks), typeof(ObservableCollection<PageLink>), typeof(SettingsPageControl), new PropertyMetadata(new ObservableCollection<PageLink>()));
public static readonly DependencyProperty ModuleContentProperty =
DependencyProperty.Register(nameof(ModuleContent), typeof(object), typeof(SettingsPageControl), new PropertyMetadata(new Grid()));
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
PrimaryLinksControl.Focus(FocusState.Programmatic);
_ = LoadAndRenderAsync("https://raw.githubusercontent.com/MicrosoftDocs/windows-dev-docs/refs/heads/docs/hub/powertoys/advanced-paste.md");
}
private sealed class TocItem
{
public string Id { get; init; } = string.Empty;
public string Title { get; init; } = string.Empty;
public int Level { get; init; }
}
private async Task LoadAndRenderAsync(string requestUrl)
{
using var client = new HttpClient();
var raw = await client.GetStringAsync(requestUrl);
// Preprocess with knowledge of the file URL (so we resolve ../images/...)
var md = PreprocessMarkdown(raw, requestUrl);
var tocItems = BuildDocumentAndAnchors(md);
// Bind ToC (indent H2/H3 a bit)
TocList.ItemsSource = tocItems.Select(i => new
{
i.Id,
i.Title,
Indent = new Thickness((i.Level - 1) * 12, 6, 8, 6),
}).ToList();
}
private List<TocItem> BuildDocumentAndAnchors(string md)
{
_fullMarkdown = md;
DocHost.Children.Clear();
_anchors.Clear();
_allHeadings.Clear();
var doc = Markdig.Markdown.Parse(md, _pipeline);
// Build slugs for ALL headings (H1..H6) so section flyouts can target any level
var rawHeadings = doc.Descendants<HeadingBlock>().ToList();
var seen = new Dictionary<string, int>();
foreach (var hb in rawHeadings)
{
string title = hb.Inline?.FirstChild?.ToString() ?? "Section";
string id = MakeSlug(title);
if (seen.TryGetValue(id, out int n))
{
n++;
seen[id] = n;
id = $"{id}-{n}";
}
else
{
seen[id] = 1;
}
_allHeadings.Add(new HeadingInfo
{
Id = id,
Title = title,
Level = hb.Level,
Start = hb.Span.Start,
End = md.Length, // fixed below
});
}
// Compute section End = next heading with level <= current level (or EOF)
for (int i = 0; i < _allHeadings.Count; i++)
{
for (int j = i + 1; j < _allHeadings.Count; j++)
{
if (_allHeadings[j].Level <= _allHeadings[i].Level)
{
_allHeadings[i].End = _allHeadings[j].Start;
break;
}
}
}
// Render the document in H2/H3 chunks for this UI
var headings = _allHeadings.Where(h => h.Level is 2 or 3).ToList();
var toc = new List<TocItem>();
if (headings.Count == 0)
{
DocHost.Children.Add(new MarkdownTextBlock { Text = md });
return toc;
}
foreach (var h in headings)
{
toc.Add(new TocItem { Id = h.Id, Title = h.Title, Level = h.Level });
// Invisible anchor just before the rendered section
var anchor = new Border { Height = 0, Opacity = 0, Tag = h.Id };
DocHost.Children.Add(anchor);
_anchors[h.Id] = anchor;
// Render this sections markdown (include heading line)
string sectionMd = md.Substring(h.Start, h.End - h.Start);
var mdtb = new MarkdownTextBlock { Text = sectionMd };
// NOTE: some toolkit versions use LinkClicked; you used OnLinkClicked in your snippet.
// Keep your version:
mdtb.OnLinkClicked += Markdown_LinkClicked;
DocHost.Children.Add(mdtb);
}
return toc;
}
private void Markdown_LinkClicked(object sender, CommunityToolkit.WinUI.Controls.LinkClickedEventArgs e)
{
var uri = e.Uri;
if (uri is null)
{
return;
}
string anchorId = null;
#pragma warning disable CA1310 // Specify StringComparison for correctness
#pragma warning disable CA1866 // Use char overload
if (!uri.IsAbsoluteUri && uri.OriginalString.StartsWith("#"))
{
anchorId = uri.OriginalString.TrimStart('#');
}
else if (uri.IsAbsoluteUri && !string.IsNullOrEmpty(uri.Fragment))
{
anchorId = uri.Fragment.TrimStart('#');
}
#pragma warning restore CA1866 // Use char overload
#pragma warning restore CA1310 // Specify StringComparison for correctness
if (!string.IsNullOrEmpty(anchorId) && _anchors.TryGetValue(anchorId, out _))
{
ScrollToAnchor(anchorId, TopOffset);
return;
}
_ = Launcher.LaunchUriAsync(uri);
}
private const double TopOffset = 40; // pixels
// Click in ToC -> scroll to anchor
private void TocList_ItemClick(object sender, ItemClickEventArgs e)
{
if (e.ClickedItem is FrameworkElement fe && fe.Tag is string id)
{
ScrollToAnchor(id, TopOffset);
return;
}
var idProp = e.ClickedItem?.GetType().GetProperty("Id")?.GetValue(e.ClickedItem) as string;
if (!string.IsNullOrEmpty(idProp))
{
ScrollToAnchor(idProp!, TopOffset);
}
}
private void ScrollToAnchor(string id, double topOffset = 0)
{
if (_anchors.TryGetValue(id, out var target))
{
var opts = new BringIntoViewOptions
{
VerticalAlignmentRatio = 0.0,
HorizontalAlignmentRatio = 0.0,
AnimationDesired = true,
};
target.StartBringIntoView(opts);
}
}
// ----------------------------
// Public API: show a section in a flyout (for any H1..H6)
// ----------------------------
public bool TryShowSectionFlyout(FrameworkElement placementTarget, string sectionId, bool includeHeading = false, FlyoutPlacementMode placement = FlyoutPlacementMode.Bottom)
{
if (placementTarget is null || string.IsNullOrWhiteSpace(sectionId))
{
return false;
}
var h = _allHeadings.FirstOrDefault(x => string.Equals(x.Id, sectionId, StringComparison.OrdinalIgnoreCase));
if (h is null)
{
return false;
}
var slice = _fullMarkdown.Substring(h.Start, h.End - h.Start);
if (!includeHeading)
{
int nl = slice.IndexOf('\n');
slice = nl >= 0 ? slice[(nl + 1)..] : string.Empty;
}
if (string.IsNullOrWhiteSpace(slice))
{
return false;
}
var title = new TextBlock
{
Text = h.Title,
TextWrapping = TextWrapping.Wrap,
Margin = new Thickness(0, 0, 0, 8),
Style = (Style)Application.Current.Resources["SubtitleTextBlockStyle"],
};
var body = new MarkdownTextBlock { Text = slice };
body.OnLinkClicked += Markdown_LinkClicked;
var content = new StackPanel { MinWidth = 320, MaxWidth = 560 };
content.Children.Add(title);
content.Children.Add(new ScrollViewer
{
Content = body,
MaxHeight = 420,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
});
var flyout = new Microsoft.UI.Xaml.Controls.Flyout { Content = content, Placement = placement };
flyout.ShowAt(placementTarget);
return true;
}
// ----------------------------
// Markdown preprocessor (MS Learn → standard Markdown)
// ----------------------------
public static string PreprocessMarkdown(string markdown, string sourceFileUrl)
{
// Compute the *directory* of the md file (guaranteed trailing slash)
var baseDir = new Uri(new Uri(sourceFileUrl), ".");
string Resolve(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
return url;
}
if (Uri.IsWellFormedUriString(url, UriKind.Absolute))
{
return url;
}
return new Uri(baseDir, url).ToString();
}
// 1) Strip YAML front matter at the very top
markdown = Regex.Replace(
markdown,
pattern: @"\A---\s*[\s\S]*?^\s*---\s*$\r?\n?",
replacement: string.Empty,
options: RegexOptions.Multiline);
// 2) Remove specific Learn notice (example you had)
markdown = Regex.Replace(
markdown,
@"^>\s*\[!IMPORTANT\]\s*> - Phi Silica is not available in China\.\s*$\r?\n?",
string.Empty,
RegexOptions.Multiline | RegexOptions.IgnoreCase);
// 3) Convert Learn admonitions to simpler blockquotes with icons
var admonitions = new (string Pattern, string Replacement)[]
{
(@"^>\s*\[!IMPORTANT\]", "> ** Important:**"),
(@"^>\s*\[!NOTE\]", "> **❗ Note:**"),
(@"^>\s*\[!TIP\]", "> **💡 Tip:**"),
(@"^>\s*\[!WARNING\]", "> **⚠️ Warning:**"),
(@"^>\s*\[!CAUTION\]", "> **⚠️ Caution:**"),
};
foreach (var (pat, rep) in admonitions)
markdown = Regex.Replace(markdown, pat, rep, RegexOptions.Multiline | RegexOptions.IgnoreCase);
// 4) Convert :::image ... ::: blocks
markdown = Regex.Replace(
markdown,
@":::image\s+(?<attrs>.*?):::",
m =>
{
string attrs = m.Groups["attrs"].Value;
static string A(string attrs, string name)
{
var mm = Regex.Match(attrs, $@"\b{name}\s*=\s*""([^""]*)""", RegexOptions.IgnoreCase);
return mm.Success ? mm.Groups[1].Value : string.Empty;
}
string src = A(attrs, "source");
string alt = A(attrs, "alt-text");
string lightbox = A(attrs, "lightbox");
string link = A(attrs, "link");
src = Resolve(src);
lightbox = Resolve(lightbox);
link = Resolve(link);
var img = $"![{alt}]";
if (!string.IsNullOrWhiteSpace(src))
{
img += $"({src})";
}
var href = !string.IsNullOrWhiteSpace(link) ? link : lightbox;
if (!string.IsNullOrWhiteSpace(href))
{
img = $"[{img}]({href})";
}
return img + "\n";
},
RegexOptions.Singleline | RegexOptions.IgnoreCase);
// 5) Resolve relative links in standard markdown
markdown = Regex.Replace(
markdown,
@"\]\((?!https?://|mailto:|data:|#)(?<rel>[^)]+)\)",
m =>
{
var rel = m.Groups["rel"].Value.Trim();
var abs = Resolve(rel);
return $"]({abs})";
});
return markdown;
}
private static string MakeSlug(string s)
{
if (string.IsNullOrWhiteSpace(s))
{
return "section";
}
var slug = s.Trim().ToLowerInvariant();
slug = Regex.Replace(slug, @"[^\p{L}\p{Nd}\s-]", string.Empty);
slug = Regex.Replace(slug, @"\s+", "-");
slug = Regex.Replace(slug, @"-+", "-");
return slug;
}
}
// ------------------------------------------------------------
// Attached property: set DocSectionFlyout.SectionId on any Button
// inside ModuleContent, and it will open a flyout for that section.
// ------------------------------------------------------------
#pragma warning disable SA1402 // File may only contain a single type
public static class DocSectionFlyout
#pragma warning restore SA1402 // File may only contain a single type
{
public static readonly DependencyProperty SectionIdProperty =
DependencyProperty.RegisterAttached(
"SectionId",
typeof(string),
typeof(DocSectionFlyout),
new PropertyMetadata(null, OnSectionIdChanged));
public static void SetSectionId(DependencyObject obj, string value) => obj.SetValue(SectionIdProperty, value);
public static string GetSectionId(DependencyObject obj) => (string)obj.GetValue(SectionIdProperty);
public static readonly DependencyProperty IncludeHeadingProperty =
DependencyProperty.RegisterAttached(
"IncludeHeading",
typeof(bool),
typeof(DocSectionFlyout),
new PropertyMetadata(false));
public static void SetIncludeHeading(DependencyObject obj, bool value) => obj.SetValue(IncludeHeadingProperty, value);
public static bool GetIncludeHeading(DependencyObject obj) => (bool)obj.GetValue(IncludeHeadingProperty);
public static readonly DependencyProperty PlacementProperty =
DependencyProperty.RegisterAttached(
"Placement",
typeof(FlyoutPlacementMode),
typeof(DocSectionFlyout),
new PropertyMetadata(FlyoutPlacementMode.Bottom));
public static void SetPlacement(DependencyObject obj, FlyoutPlacementMode value) => obj.SetValue(PlacementProperty, value);
public static FlyoutPlacementMode GetPlacement(DependencyObject obj) => (FlyoutPlacementMode)obj.GetValue(PlacementProperty);
private static void OnSectionIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ButtonBase btn)
{
btn.Click -= Button_Click;
if (e.NewValue is string { Length: > 0 })
{
btn.Click += Button_Click;
}
}
}
private static void Button_Click(object sender, RoutedEventArgs e)
{
if (sender is not FrameworkElement fe)
{
return;
}
// Find nearest SettingsPageControl ancestor
var parent = fe as DependencyObject;
SettingsPageControl host = null;
while (parent is not null)
{
parent = VisualTreeHelper.GetParent(parent);
if (parent is SettingsPageControl spc)
{
host = spc;
break;
}
}
if (host is null)
{
return;
}
var id = GetSectionId(fe);
if (string.IsNullOrWhiteSpace(id))
{
return;
}
var includeHeading = GetIncludeHeading(fe);
var placement = GetPlacement(fe);
host.TryShowSectionFlyout(fe, id, includeHeading, placement);
}
}
}

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
x:Name="ShortcutContentControl"
mc:Ignorable="d">
<Grid MinWidth="498" MinHeight="220">
@@ -71,9 +71,8 @@
Message="{Binding ElementName=ShortcutContentControl, Path=ConflictMessage, Mode=OneWay}"
Severity="Warning" />
</Grid>
<tk7controls:MarkdownTextBlock
<tkcontrols:MarkdownTextBlock
x:Uid="InvalidShortcutWarningLabel"
Background="Transparent"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</StackPanel>

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
@@ -38,11 +38,10 @@
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<tk7controls:MarkdownTextBlock
<tkcontrols:MarkdownTextBlock
x:Name="LabelControl"
Grid.Column="1"
VerticalAlignment="Center"
Background="Transparent"
Text="{x:Bind Text}" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LabelPlacementStates">

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_AlwaysOnTop" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/AlwaysOnTop.png">
@@ -17,7 +17,7 @@
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_AlwaysOnTop_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_AlwaysOnTop_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_Awake" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/Awake.png">
@@ -13,11 +13,11 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_Awake_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_Awake_HowToUse" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_Awake_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_Awake_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_CmdNotFound" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/CmdNotFound.png">
@@ -13,7 +13,7 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_CmdNotFound_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_CmdNotFound_HowToUse" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_CmdPal" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/CmdPal.png">
@@ -17,7 +17,7 @@
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_CmdPal_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_CmdPal_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_ColorPicker" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/ColorPicker.gif">
@@ -17,7 +17,7 @@
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_ColorPicker_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_ColorPicker_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_FancyZones" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/FancyZones.gif">
@@ -13,12 +13,12 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_FancyZones_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_FancyZones_HowToUse" />
<controls:ShortcutWithTextLabelControl x:Name="HotkeyControl" x:Uid="Oobe_FancyZones_HowToUse_Shortcut" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_FancyZones_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_FancyZones_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_FileExplorer" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/FileExplorer.png">
@@ -13,7 +13,7 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToEnable" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_FileExplorer_HowToEnable" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_FileExplorer_HowToEnable" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_FileLocksmith" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/FileLocksmith.gif">
@@ -13,11 +13,11 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_FileLocksmith_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_FileLocksmith_HowToUse" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_FileLocksmith_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_FileLocksmith_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_ImageResizer" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/ImageResizer.gif">
@@ -13,11 +13,11 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToLaunch" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_ImageResizer_HowToLaunch" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_ImageResizer_HowToLaunch" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_ImageResizer_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_ImageResizer_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_KBM" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/KBM.gif">
@@ -13,11 +13,11 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToCreateMappings" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_KBM_HowToCreateMappings" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_KBM_HowToCreateMappings" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_KBM_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_KBM_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_MeasureTool" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/ScreenRuler.gif">
@@ -15,7 +15,7 @@
<controls:ShortcutWithTextLabelControl x:Name="HotkeyActivation" x:Uid="Oobe_MeasureTool_Activation" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_MeasureTool_HowToLaunch" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_MeasureTool_HowToLaunch" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,23 +5,23 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_MouseUtils" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/MouseUtils.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_MouseUtils_FindMyMouse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_MouseUtils_FindMyMouse_Description" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_MouseUtils_FindMyMouse_Description" />
<TextBlock x:Uid="Oobe_MouseUtils_MouseHighlighter" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_MouseUtils_MouseHighlighter_Description" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_MouseUtils_MouseHighlighter_Description" />
<TextBlock x:Uid="Oobe_MouseUtils_MousePointerCrosshairs" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_MouseUtils_MousePointerCrosshairs_Description" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_MouseUtils_MousePointerCrosshairs_Description" />
<TextBlock x:Uid="Oobe_MouseUtils_MouseJump" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_MouseUtils_MouseJump_Description" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_MouseUtils_MouseJump_Description" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_MouseWithoutBorders" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/MouseWithoutBorders.png">
@@ -14,11 +14,11 @@
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_MouseWithoutBorders_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_MouseWithoutBorders_HowToUse" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_MouseWithoutBorders_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_MouseWithoutBorders_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<!-- TODO: Create New+ overview .gif and update ref here -->
@@ -13,10 +13,10 @@
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_NewPlus_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_NewPlus_HowToUse" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_NewPlus_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_NewPlus_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -7,7 +7,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
Loaded="Page_Loaded"
mc:Ignorable="d">

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_QuickAccent" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/QuickAccent.gif">
@@ -13,7 +13,7 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_QuickAccent_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_QuickAccent_HowToUse" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_TextExtractor" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/TextExtractor.gif">
@@ -17,7 +17,7 @@
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_TextExtractor_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_TextExtractor_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_PowerRename" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/PowerRename.gif">
@@ -13,11 +13,11 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_PowerRename_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_PowerRename_HowToUse" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_PowerRename_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_PowerRename_TipsAndTricks" />
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_RegistryPreview" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/RegistryPreview.png">
@@ -13,11 +13,11 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_RegistryPreview_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_RegistryPreview_HowToUse" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_RegistryPreview_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_RegistryPreview_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_Run" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/Run.gif">
@@ -17,7 +17,7 @@
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_Run_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_Run_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button

View File

@@ -5,11 +5,25 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
Loaded="Page_Loaded"
mc:Ignorable="d">
<Page.Resources>
<tkcontrols:MarkdownThemes
x:Key="ReleaseNotesMarkdownThemeConfig"
H1FontSize="22"
H1FontWeight="SemiBold"
H1Margin="0, 36, 0, 8"
H2FontSize="16"
H2FontWeight="SemiBold"
H2Margin="0, 16, 0, 4"
H3FontSize="16"
H3FontWeight="SemiBold"
H3Margin="0, 16, 0, 4"
HeadingForeground="{StaticResource TextFillColorPrimaryBrush}" />
<tkcontrols:MarkdownConfig x:Key="ReleaseNotesMarkdownConfig" Themes="{StaticResource ReleaseNotesMarkdownThemeConfig}" />
</Page.Resources>
<!-- Main layout container -->
<Grid>
@@ -163,23 +177,14 @@
VerticalAlignment="Center"
IsIndeterminate="True"
Visibility="Visible" />
<tk7controls:MarkdownTextBlock
<tkcontrols:MarkdownTextBlock
x:Name="ReleaseNotesMarkdown"
VerticalAlignment="Top"
Background="Transparent"
Header1FontSize="20"
Header1FontWeight="SemiBold"
Header1Margin="0,0,0,4"
Header3FontSize="16"
Header3FontWeight="SemiBold"
Header4FontSize="16"
Header4FontWeight="SemiBold"
HorizontalRuleMargin="24"
LinkClicked="ReleaseNotesMarkdown_LinkClicked"
ListMargin="-18,4,0,12"
ParagraphMargin="0,0,0,0"
TableMargin="24"
Visibility="Collapsed" />
Config="{StaticResource ReleaseNotesMarkdownConfig}"
UseAutoLinks="True"
UseEmphasisExtras="True"
UseListExtras="True"
UsePipeTables="True"
UseTaskLists="True" />
</Grid>
</ScrollViewer>
</Grid>

View File

@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
@@ -13,8 +12,7 @@ using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CommunityToolkit.WinUI.UI.Controls;
using CommunityToolkit.WinUI.Controls;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Helpers;
@@ -25,7 +23,10 @@ using Microsoft.PowerToys.Settings.UI.SerializationContext;
using Microsoft.PowerToys.Settings.UI.Services;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
@@ -257,17 +258,6 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
}
}
private void ReleaseNotesMarkdown_LinkClicked(object sender, LinkClickedEventArgs e)
{
if (Uri.TryCreate(e.Link, UriKind.Absolute, out Uri link))
{
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
Process.Start(new ProcessStartInfo(link.ToString()) { UseShellExecute = true });
});
}
}
private void DataDiagnostics_InfoBar_YesNo_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
string commandArg = string.Empty;

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_Workspaces" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/Workspaces.png">
@@ -13,12 +13,12 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_Workspaces_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_Workspaces_HowToUse" />
<controls:ShortcutWithTextLabelControl x:Name="HotkeyControl" x:Uid="Oobe_Workspaces_HowToUse_Shortcut" />
<TextBlock x:Uid="Oobe_TipsAndTricks" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_Workspaces_TipsAndTricks" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_Workspaces_TipsAndTricks" />
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -5,7 +5,7 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_ZoomIt" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/ZoomIt.gif">
@@ -13,7 +13,7 @@
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<tk7controls:MarkdownTextBlock x:Uid="Oobe_ZoomIt_HowToUse" Background="Transparent" />
<tkcontrols:MarkdownTextBlock x:Uid="Oobe_ZoomIt_HowToUse" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />

View File

@@ -21,13 +21,16 @@
</ResourceDictionary>
</UserControl.Resources>
<controls:SettingsGroup x:Uid="MouseUtils_MouseJump">
<controls:SettingsGroup x:Uid="MouseUtils_MouseJump" AutomationProperties.AutomationId="MouseUtils_MouseJumpTestId">
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.IsJumpEnabledGpoConfigured, Mode=OneWay}">
<tkcontrols:SettingsCard
x:Name="MouseUtilsEnableMouseJump"
x:Uid="MouseUtils_Enable_MouseJump"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/MouseJump.png}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsMouseJumpEnabled, Mode=TwoWay}" />
<ToggleSwitch
x:Uid="ToggleSwitch"
AutomationProperties.AutomationId="MouseUtils_MouseJumpToggleId"
IsOn="{x:Bind ViewModel.IsMouseJumpEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:GPOInfoControl>

View File

@@ -46,6 +46,9 @@
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
Orientation="Vertical"
Spacing="2">
<StackPanel Orientation="Horizontal" Spacing="8">
<!-- Include the heading line in the flyout and place it at the right -->
</StackPanel>
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}">
<tkcontrols:SettingsCard
Name="AdvancedPasteEnableToggleControlHeaderText"
@@ -86,7 +89,11 @@
<tkcontrols:SettingsCard.Description>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="AdvancedPaste_EnableAISettingsCardDescription" />
<HyperlinkButton x:Uid="AdvancedPaste_EnableAISettingsCardDescriptionLearnMore" NavigateUri="https://learn.microsoft.com/windows/powertoys/advanced-paste" />
<HyperlinkButton
x:Uid="AdvancedPaste_EnableAISettingsCardDescriptionLearnMore"
controls:DocSectionFlyout.IncludeHeading="True"
controls:DocSectionFlyout.Placement="Right"
controls:DocSectionFlyout.SectionId="paste-text-with-ai" />
</StackPanel>
</tkcontrols:SettingsCard.Description>
</tkcontrols:SettingsCard>

View File

@@ -5,14 +5,12 @@
using System;
using System.IO;
using System.IO.Abstractions;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml.Controls;
using PowerToys.GPOWrapper;
namespace Microsoft.PowerToys.Settings.UI.Views

View File

@@ -19,7 +19,10 @@
Name="FancyZonesEnableToggleControlHeaderText"
x:Uid="FancyZones_EnableToggleControl_HeaderText"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/FancyZones.png}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
<ToggleSwitch
x:Uid="ToggleSwitch"
AutomationProperties.AutomationId="EnableFancyZonesToggleSwitch"
IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:GPOInfoControl>
<controls:SettingsGroup x:Uid="FancyZones_Editor_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">

View File

@@ -9,7 +9,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="using:Microsoft.PowerToys.Settings.UI.Library"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:toolkitconverters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
xmlns:ui="using:CommunityToolkit.WinUI"
x:Name="RootPage"
AutomationProperties.LandmarkType="Main"
@@ -23,7 +23,7 @@
<converters:ImageResizerDoubleToAutoConverter x:Key="ImageResizerDoubleToAutoConverter" />
<converters:ImageResizerNumberBoxValueConverter x:Key="ImageResizerNumberBoxValueConverter" />
<converters:ImageResizerZeroToEmptyStringNumberFormatter x:Key="ImageResizerZeroToEmptyStringNumberFormatter" />
<toolkitconverters:BoolToObjectConverter
<tkconverters:BoolToObjectConverter
x:Key="BoolToComboBoxIndexConverter"
FalseValue="1"
TrueValue="0" />

View File

@@ -23,18 +23,22 @@
<controls:SettingsPageControl x:Uid="MouseUtils" ModuleImageSource="ms-appx:///Assets/Settings/Modules/MouseUtils.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
<controls:SettingsGroup x:Uid="MouseUtils_FindMyMouse">
<controls:SettingsGroup x:Uid="MouseUtils_FindMyMouse" AutomationProperties.AutomationId="MouseUtils_FindMyMouseTestId">
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.IsFindMyMouseEnabledGpoConfigured, Mode=OneWay}">
<tkcontrols:SettingsCard
Name="MouseUtilsEnableFindMyMouse"
x:Uid="MouseUtils_Enable_FindMyMouse"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/FindMyMouse.png}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=TwoWay}" />
<ToggleSwitch
x:Uid="ToggleSwitch"
AutomationProperties.AutomationId="MouseUtils_FindMyMouseToggleId"
IsOn="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:GPOInfoControl>
<tkcontrols:SettingsExpander
Name="MouseUtilsFindMyMouseActivationMethod"
x:Uid="MouseUtils_FindMyMouse_ActivationMethod"
AutomationProperties.AutomationId="MouseUtils_FindMyMouseActivationMethodId"
HeaderIcon="{ui:FontIcon Glyph=&#xE961;}"
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}"
IsExpanded="True">
@@ -108,6 +112,7 @@
<tkcontrols:SettingsExpander
Name="FindMyMouseAppearanceBehavior"
x:Uid="Appearance_Behavior"
AutomationProperties.AutomationId="MouseUtils_FindMyMouseAppearanceBehaviorId"
HeaderIcon="{ui:FontIcon Glyph=&#xEB3C;}"
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}"
IsExpanded="False">
@@ -115,19 +120,21 @@
<tkcontrols:SettingsCard Name="MouseUtilsFindMyMouseOverlayOpacity" x:Uid="MouseUtils_FindMyMouse_OverlayOpacity">
<Slider
MinWidth="{StaticResource SettingActionControlMinWidth}"
AutomationProperties.AutomationId="MouseUtils_FindMyMouseOverlayOpacityId"
Maximum="100"
Minimum="1"
Value="{x:Bind ViewModel.FindMyMouseOverlayOpacity, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard Name="MouseUtilsFindMyMouseBackgroundColor" x:Uid="MouseUtils_FindMyMouse_BackgroundColor">
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.FindMyMouseBackgroundColor, Mode=TwoWay}" />
<controls:ColorPickerButton AutomationProperties.AutomationId="MouseUtils_FindMyMouseBackgroundColorId" SelectedColor="{x:Bind Path=ViewModel.FindMyMouseBackgroundColor, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard Name="MouseUtilsFindMyMouseSpotlightColor" x:Uid="MouseUtils_FindMyMouse_SpotlightColor">
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.FindMyMouseSpotlightColor, Mode=TwoWay}" />
<controls:ColorPickerButton AutomationProperties.AutomationId="MouseUtils_FindMyMouseSpotlightColorId" SelectedColor="{x:Bind Path=ViewModel.FindMyMouseSpotlightColor, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard Name="MouseUtilsFindMyMouseSpotlightRadius" x:Uid="MouseUtils_FindMyMouse_SpotlightRadius">
<NumberBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
AutomationProperties.AutomationId="MouseUtils_FindMyMouseSpotlightRadiusId"
LargeChange="10"
Minimum="5"
SmallChange="1"
@@ -137,6 +144,7 @@
<tkcontrols:SettingsCard Name="MouseUtilsFindMyMouseSpotlightInitialZoom" x:Uid="MouseUtils_FindMyMouse_SpotlightInitialZoom">
<Slider
MinWidth="{StaticResource SettingActionControlMinWidth}"
AutomationProperties.AutomationId="MouseUtils_FindMyMouseSpotlightZoomId"
Maximum="40"
Minimum="1"
Value="{x:Bind ViewModel.FindMyMouseSpotlightInitialZoom, Mode=TwoWay}" />
@@ -144,6 +152,7 @@
<tkcontrols:SettingsCard Name="MouseUtilsFindMyMouseAnimationDurationMs" x:Uid="MouseUtils_FindMyMouse_AnimationDurationMs">
<NumberBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
AutomationProperties.AutomationId="MouseUtils_FindMyMouseAnimationDurationId"
IsEnabled="{x:Bind ViewModel.IsAnimationEnabledBySystem, Mode=OneWay}"
LargeChange="100"
Minimum="0"
@@ -166,6 +175,7 @@
<tkcontrols:SettingsExpander
Name="MouseUtilsFindMyMouseExcludedApps"
x:Uid="MouseUtils_FindMyMouse_ExcludedApps"
AutomationProperties.AutomationId="MouseUtils_FindMyMouseExcludedAppsId"
HeaderIcon="{ui:FontIcon Glyph=&#xECE4;}"
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander.Items>
@@ -186,18 +196,22 @@
</tkcontrols:SettingsExpander>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="MouseUtils_MouseHighlighter">
<controls:SettingsGroup x:Uid="MouseUtils_MouseHighlighter" AutomationProperties.AutomationId="MouseUtils_MouseHighlighterTestId">
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.IsHighlighterEnabledGpoConfigured, Mode=OneWay}">
<tkcontrols:SettingsCard
Name="MouseUtilsEnableMouseHighlighter"
x:Uid="MouseUtils_Enable_MouseHighlighter"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/MouseHighlighter.png}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=TwoWay}" />
<ToggleSwitch
x:Uid="ToggleSwitch"
AutomationProperties.AutomationId="MouseUtils_MouseHighlighterToggleId"
IsOn="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:GPOInfoControl>
<tkcontrols:SettingsExpander
Name="MouseUtilsMouseHighlighterActivationShortcut"
x:Uid="MouseUtils_MouseHighlighter_ActivationShortcut"
AutomationProperties.AutomationId="MouseUtils_MouseHighlighterActivationShortcutId"
HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}"
IsEnabled="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=OneWay}"
IsExpanded="True">
@@ -211,6 +225,7 @@
<tkcontrols:SettingsExpander
Name="MouseHighlighterAppearanceBehavior"
x:Uid="Appearance_Behavior"
AutomationProperties.AutomationId="MouseUtils_MouseHighlighterAppearanceBehaviorId"
HeaderIcon="{ui:FontIcon Glyph=&#xEB3C;}"
IsEnabled="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander.Items>
@@ -265,13 +280,16 @@
<panels:MouseJumpPanel x:Name="MouseUtils_MouseJump_Panel" x:Uid="MouseUtils_MouseJump_Panel" />
<controls:SettingsGroup x:Uid="MouseUtils_MousePointerCrosshairs">
<controls:SettingsGroup x:Uid="MouseUtils_MousePointerCrosshairs" AutomationProperties.AutomationId="MouseUtils_MousePointerCrosshairsTestId">
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.IsMousePointerCrosshairsEnabledGpoConfigured, Mode=OneWay}">
<tkcontrols:SettingsCard
Name="MouseUtilsEnableMousePointerCrosshairs"
x:Uid="MouseUtils_Enable_MousePointerCrosshairs"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/MouseCrosshairs.png}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsMousePointerCrosshairsEnabled, Mode=TwoWay}" />
<ToggleSwitch
x:Uid="ToggleSwitch"
AutomationProperties.AutomationId="MouseUtils_MousePointerCrosshairsToggleId"
IsOn="{x:Bind ViewModel.IsMousePointerCrosshairsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:GPOInfoControl>
@@ -292,6 +310,7 @@
<tkcontrols:SettingsExpander
Name="MousePointerCrosshairsAppearanceBehavior"
x:Uid="Appearance_Behavior"
AutomationProperties.AutomationId="MouseUtils_MousePointerCrosshairsAppearanceBehaviorId"
HeaderIcon="{ui:FontIcon Glyph=&#xEB3C;}"
IsEnabled="{x:Bind ViewModel.IsMousePointerCrosshairsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander.Items>

View File

@@ -3,17 +3,17 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
xmlns:ui="using:CommunityToolkit.WinUI"
AutomationProperties.LandmarkType="Main"
mc:Ignorable="d">
<local:NavigablePage.Resources>
<converters:BoolToVisibilityConverter x:Key="negativeBoolToVisibilityConverter" />
<converters:BoolToObjectConverter
<tkconverters:BoolToVisibilityConverter x:Key="negativeBoolToVisibilityConverter" />
<tkconverters:BoolToObjectConverter
x:Key="OneRowMatrixBoolToNumberOfRowsConverter"
FalseValue="2"
TrueValue="4" />

View File

@@ -8,6 +8,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="using:Settings.UI.Library"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:vm="using:Microsoft.PowerToys.Settings.UI.ViewModels"
x:Name="RootPage"
@@ -16,13 +17,20 @@
<Page.Resources>
<converters:IconConverter x:Key="IconConverter" />
<tkconverters:CollectionVisibilityConverter x:Key="CollectionVisibilityConverter" />
</Page.Resources>
<controls:SettingsPageControl x:Name="PageControl" x:Uid="SearchResults_Title">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Margin="0,-40,0,0" Orientation="Vertical">
<controls:SettingsGroup x:Uid="SearchResults_ModulesTitle" Margin="0,-10,0,0">
<ItemsControl x:Name="ModulesItemsControl" ItemsSource="{x:Bind ViewModel.ModuleResults, Mode=OneWay}">
<controls:SettingsGroup
x:Uid="SearchResults_ModulesTitle"
Margin="0,-10,0,0"
Visibility="{x:Bind ViewModel.ModuleResults, Mode=OneWay, Converter={StaticResource CollectionVisibilityConverter}}">
<ItemsControl
x:Name="ModulesItemsControl"
IsTabStop="False"
ItemsSource="{x:Bind ViewModel.ModuleResults, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="models:SettingEntry">
<tkcontrols:SettingsCard
@@ -37,11 +45,14 @@
</controls:SettingsGroup>
<!-- Settings Groups -->
<ItemsControl x:Name="SettingsGroupsItemsControl" ItemsSource="{x:Bind ViewModel.GroupedSettingsResults, Mode=OneWay}">
<ItemsControl
x:Name="SettingsGroupsItemsControl"
IsTabStop="False"
ItemsSource="{x:Bind ViewModel.GroupedSettingsResults, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:SettingsGroup">
<controls:SettingsGroup Header="{x:Bind GroupName}">
<ItemsControl ItemsSource="{x:Bind Settings}">
<ItemsControl IsTabStop="False" ItemsSource="{x:Bind Settings}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="models:SettingEntry">
<tkcontrols:SettingsCard
@@ -72,6 +83,7 @@
Glyph="&#xE71C;" />
<TextBlock HorizontalAlignment="Center" TextAlignment="Center">
<Run x:Uid="SearchResults_NoResultsHeader" FontWeight="SemiBold" />
<LineBreak />
<Run x:Uid="SearchResults_NoResultsDescription" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</TextBlock>
</StackPanel>