mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-07 21:06:58 +01:00
Compare commits
27 Commits
dev/featur
...
dev/jaime/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b605fb633 | ||
|
|
d64642f29c | ||
|
|
57b06fa431 | ||
|
|
7b37eba0f9 | ||
|
|
24bed6f0bb | ||
|
|
74fbc519ab | ||
|
|
3b7adbe6ac | ||
|
|
8b8c75b9a5 | ||
|
|
5c257fb3db | ||
|
|
6e141f89c9 | ||
|
|
62c7b0a66d | ||
|
|
9509d7c1cc | ||
|
|
6043898ee5 | ||
|
|
136b239f96 | ||
|
|
c148b51698 | ||
|
|
1ae8327a43 | ||
|
|
aa977f7579 | ||
|
|
dcbff83d8c | ||
|
|
5c631bd2c7 | ||
|
|
c252d87573 | ||
|
|
92483aee1a | ||
|
|
2eec4c5a98 | ||
|
|
109f0b210a | ||
|
|
f019163083 | ||
|
|
deb6234d72 | ||
|
|
cdf5677eb9 | ||
|
|
bc0811e6a1 |
@@ -9,7 +9,7 @@
|
||||
]
|
||||
},
|
||||
"xamlstyler.console": {
|
||||
"version": "3.2206.4",
|
||||
"version": "3.2404.2",
|
||||
"commands": [
|
||||
"xstyler"
|
||||
]
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -68,7 +68,6 @@ body:
|
||||
- Peek
|
||||
- PowerRename
|
||||
- PowerToys Run
|
||||
- Projects
|
||||
- Quick Accent
|
||||
- Registry Preview
|
||||
- Screen ruler
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/translation_issue.yml
vendored
1
.github/ISSUE_TEMPLATE/translation_issue.yml
vendored
@@ -42,7 +42,6 @@ body:
|
||||
- Peek
|
||||
- PowerRename
|
||||
- PowerToys Run
|
||||
- Projects
|
||||
- Quick Accent
|
||||
- Registry Preview
|
||||
- Screen ruler
|
||||
|
||||
5
.github/actions/spell-check/allow/code.txt
vendored
5
.github/actions/spell-check/allow/code.txt
vendored
@@ -221,3 +221,8 @@ artanh
|
||||
arsinh
|
||||
arcosh
|
||||
|
||||
# Linux
|
||||
|
||||
dbus
|
||||
anypass
|
||||
gpg
|
||||
|
||||
20
.github/actions/spell-check/expect.txt
vendored
20
.github/actions/spell-check/expect.txt
vendored
@@ -61,7 +61,6 @@ appmanifest
|
||||
APPNAME
|
||||
appref
|
||||
appsettings
|
||||
appsfolder
|
||||
appwindow
|
||||
appwiz
|
||||
APSTUDIO
|
||||
@@ -96,6 +95,7 @@ AUTOUPDATE
|
||||
AValid
|
||||
awakeness
|
||||
AWAYMODE
|
||||
azcliversion
|
||||
azman
|
||||
backtracer
|
||||
bbwe
|
||||
@@ -120,6 +120,7 @@ BLURREGION
|
||||
bmi
|
||||
bms
|
||||
BNumber
|
||||
BODGY
|
||||
BOKMAL
|
||||
bootstrapper
|
||||
BOOTSTRAPPERINSTALLFOLDER
|
||||
@@ -166,6 +167,7 @@ CENTERALIGN
|
||||
ceq
|
||||
certlm
|
||||
certmgr
|
||||
cfp
|
||||
cguid
|
||||
CHANGECBCHAIN
|
||||
changecursor
|
||||
@@ -239,7 +241,6 @@ CONTEXTMENUHANDLER
|
||||
CONTROLL
|
||||
CONTROLPARENT
|
||||
copiedcolorrepresentation
|
||||
COREWINDOW
|
||||
cotaskmem
|
||||
COULDNOT
|
||||
countof
|
||||
@@ -756,6 +757,7 @@ KEYEVENTF
|
||||
KEYIMAGE
|
||||
keynum
|
||||
keyremaps
|
||||
keyvault
|
||||
KILLFOCUS
|
||||
killrunner
|
||||
Knownfolders
|
||||
@@ -1207,14 +1209,9 @@ PRODUCTVERSION
|
||||
Progman
|
||||
programdata
|
||||
projectname
|
||||
PROJECTSEDITOR
|
||||
PROJECTSLAUNCHER
|
||||
PROJECTSSNAPSHOTTOOL
|
||||
PROPBAG
|
||||
PROPERTYKEY
|
||||
propkey
|
||||
propsys
|
||||
PROPVARIANT
|
||||
propvarutil
|
||||
prvpane
|
||||
psapi
|
||||
@@ -1345,6 +1342,9 @@ RRF
|
||||
rrr
|
||||
rsop
|
||||
Rsp
|
||||
rstringalnum
|
||||
rstringalpha
|
||||
rstringdigit
|
||||
Rstrtmgr
|
||||
RTB
|
||||
RTLREADING
|
||||
@@ -1359,6 +1359,7 @@ runtimeclass
|
||||
runtimeobject
|
||||
runtimepack
|
||||
runtimes
|
||||
ruuid
|
||||
rvm
|
||||
rwin
|
||||
rwl
|
||||
@@ -1380,7 +1381,6 @@ sddl
|
||||
SDKDDK
|
||||
sdns
|
||||
searchterm
|
||||
SEARCHUI
|
||||
secpol
|
||||
SENDCHANGE
|
||||
sendinput
|
||||
@@ -1564,9 +1564,7 @@ SYSKEYUP
|
||||
SYSLIB
|
||||
SYSMENU
|
||||
SYSTEMAPPS
|
||||
systemsettings
|
||||
SYSTEMTIME
|
||||
SYSTEMWOW
|
||||
tapp
|
||||
TApplication
|
||||
TApplied
|
||||
@@ -1678,11 +1676,9 @@ urlmon
|
||||
Usb
|
||||
USEDEFAULT
|
||||
USEFILEATTRIBUTES
|
||||
USEPOSITION
|
||||
USERDATA
|
||||
Userenv
|
||||
USESHOWWINDOW
|
||||
USESIZE
|
||||
USESTDHANDLES
|
||||
USRDLL
|
||||
UType
|
||||
|
||||
94
.github/workflows/msstore-submissions.yml
vendored
94
.github/workflows/msstore-submissions.yml
vendored
@@ -5,56 +5,80 @@ on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
|
||||
microsoft_store:
|
||||
name: Publish Microsoft Store
|
||||
environment: store
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: BODGY - Set up Gnome Keyring for future Cert Auth
|
||||
run: |-
|
||||
sudo apt-get install -y gnome-keyring
|
||||
export $(dbus-launch --sh-syntax)
|
||||
export $(echo 'anypass_just_to_unlock' | gnome-keyring-daemon --unlock)
|
||||
export $(echo 'anypass_just_to_unlock' | gnome-keyring-daemon --start --components=gpg,pkcs11,secrets,ssh)
|
||||
|
||||
- name: Log in to Azure
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Get latest URL from public releases
|
||||
id: releaseVars
|
||||
run: |
|
||||
release=$(curl https://api.github.com/repos/Microsoft/PowerToys/releases | jq '[.[]|select(.name | contains("Release"))][0]')
|
||||
assets=$(jq -n "$release" | jq '.assets')
|
||||
powerToysSetup=$(jq -n "$assets" | jq '[.[]|select(.name | contains("PowerToysUserSetup"))]')
|
||||
echo ::set-output name=powerToysInstallerX64Url::$(jq -n "$powerToysSetup" | jq -r '[.[]|select(.name | contains("x64"))][0].browser_download_url')
|
||||
echo ::set-output name=powerToysInstallerArm64Url::$(jq -n "$powerToysSetup" | jq -r '[.[]|select(.name | contains("arm64"))][0].browser_download_url')
|
||||
echo powerToysInstallerX64Url=$(jq -n "$powerToysSetup" | jq -r '[.[]|select(.name | contains("x64"))][0].browser_download_url') >> $GITHUB_OUTPUT
|
||||
echo powerToysInstallerArm64Url=$(jq -n "$powerToysSetup" | jq -r '[.[]|select(.name | contains("arm64"))][0].browser_download_url') >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: microsoft/setup-msstore-cli@v1
|
||||
|
||||
- name: Fetch Store Credential
|
||||
uses: azure/cli@v2
|
||||
with:
|
||||
azcliversion: latest
|
||||
inlineScript: |-
|
||||
az keyvault secret download --vault-name ${{ secrets.AZURE_KEYVAULT_NAME }} -n ${{ secrets.AZURE_AUTH_CERT_NAME }} -f cert.pfx.b64
|
||||
base64 -d < cert.pfx.b64 > cert.pfx
|
||||
|
||||
- name: Configure Store Credentials
|
||||
uses: microsoft/store-submission@v1
|
||||
with:
|
||||
command: configure
|
||||
type: win32
|
||||
seller-id: ${{ secrets.SELLER_ID }}
|
||||
product-id: ${{ secrets.PRODUCT_ID }}
|
||||
tenant-id: ${{ secrets.TENANT_ID }}
|
||||
client-id: ${{ secrets.CLIENT_ID }}
|
||||
client-secret: ${{ secrets.CLIENT_SECRET }}
|
||||
run: |-
|
||||
msstore reconfigure -cfp cert.pfx -c ${{ secrets.AZURE_CLIENT_ID }} -t ${{ secrets.AZURE_TENANT_ID }} -s ${{ secrets.SELLER_ID }}
|
||||
|
||||
- name: Update draft submission
|
||||
uses: microsoft/store-submission@v1
|
||||
with:
|
||||
command: update
|
||||
product-update: '{
|
||||
"packages":[
|
||||
{
|
||||
"packageUrl":"${{ steps.releaseVars.outputs.powerToysInstallerX64Url }}",
|
||||
"languages":["zh-hans", "zh-hant", "en", "cs", "nl", "fr", "pt", "pt-br", "de", "hu", "it", "ja", "ko", "pl", "ru", "es", "tr"],
|
||||
"architectures":["X64"],
|
||||
"installerParameters":"/quiet /norestart",
|
||||
"isSilentInstall":true
|
||||
},
|
||||
{
|
||||
"packageUrl":"${{ steps.releaseVars.outputs.powerToysInstallerArm64Url }}",
|
||||
"languages":["zh-hans", "zh-hant", "en", "cs", "nl", "fr", "pt", "pt-br", "de", "hu", "it", "ja", "ko", "pl", "ru", "es", "tr"],
|
||||
"architectures":["Arm64"],
|
||||
"installerParameters":"/quiet /norestart",
|
||||
"isSilentInstall":true
|
||||
}
|
||||
]
|
||||
}'
|
||||
run: |-
|
||||
msstore submission update ${{ secrets.PRODUCT_ID }} '{
|
||||
"packages":[
|
||||
{
|
||||
"packageUrl":"${{ steps.releaseVars.outputs.powerToysInstallerX64Url }}",
|
||||
"languages":["zh-hans", "zh-hant", "en", "cs", "nl", "fr", "pt", "pt-br", "de", "hu", "it", "ja", "ko", "pl", "ru", "es", "tr"],
|
||||
"architectures":["X64"],
|
||||
"installerParameters":"/quiet /norestart",
|
||||
"isSilentInstall":true
|
||||
},
|
||||
{
|
||||
"packageUrl":"${{ steps.releaseVars.outputs.powerToysInstallerArm64Url }}",
|
||||
"languages":["zh-hans", "zh-hant", "en", "cs", "nl", "fr", "pt", "pt-br", "de", "hu", "it", "ja", "ko", "pl", "ru", "es", "tr"],
|
||||
"architectures":["Arm64"],
|
||||
"installerParameters":"/quiet /norestart",
|
||||
"isSilentInstall":true
|
||||
}
|
||||
]
|
||||
}'
|
||||
|
||||
- name: Publish Submission
|
||||
uses: microsoft/store-submission@v1
|
||||
with:
|
||||
command: publish
|
||||
run: |-
|
||||
msstore submission publish ${{ secrets.PRODUCT_ID }}
|
||||
|
||||
- name: Clean up auth certificate
|
||||
if: always()
|
||||
run: |-
|
||||
rm -f cert.pfx cert.pfx.b64
|
||||
|
||||
@@ -189,12 +189,6 @@
|
||||
"WinUI3Apps\\PowerToys.PowerRenameContextMenu.dll",
|
||||
"WinUI3Apps\\PowerRenameContextMenuPackage.msix",
|
||||
|
||||
"PowerToys.ProjectsSnapshotTool.exe",
|
||||
"PowerToys.ProjectsLauncher.exe",
|
||||
"PowerToys.ProjectsEditor.exe",
|
||||
"PowerToys.ProjectsEditor.dll",
|
||||
"PowerToys.ProjectsModuleInterface.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewExt.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.dll",
|
||||
|
||||
@@ -41,6 +41,6 @@ jobs:
|
||||
platform: arm64
|
||||
${{ if eq(variables['System.PullRequest.IsFork'], 'False') }}:
|
||||
enableCaching: true
|
||||
- template: ./templates/run-ui-tests-ci.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
# - template: ./templates/run-ui-tests-ci.yml
|
||||
# parameters:
|
||||
# platform: x64
|
||||
|
||||
@@ -24,10 +24,10 @@ jobs:
|
||||
NODE_OPTIONS: --max_old_space_size=16384
|
||||
pool:
|
||||
demands: ImageOverride -equals SHINE-VS17-Latest
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
|
||||
name: SHINE-INT-L
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-L
|
||||
timeoutInMinutes: 120
|
||||
strategy:
|
||||
maxParallel: 10
|
||||
|
||||
@@ -3,10 +3,10 @@ jobs:
|
||||
- job: Precheck
|
||||
pool:
|
||||
demands: ImageOverride -equals SHINE-VS17-Latest
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
|
||||
name: SHINE-INT-L
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-L
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ jobs:
|
||||
variables:
|
||||
SrcPath: $(Build.Repository.LocalPath)
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: SHINE-OSS-Testing-x64
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
|
||||
name: SHINE-INT-Testing-x64
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-Testing-x64
|
||||
steps:
|
||||
- checkout: self
|
||||
fetchDepth: 1
|
||||
|
||||
@@ -8,7 +8,7 @@ resources:
|
||||
- repository: 1ESPipelineTemplates
|
||||
type: git
|
||||
name: 1ESPipelineTemplates/1ESPipelineTemplates
|
||||
ref: refs/tags/release
|
||||
ref: refs/tags/release-2024-06-21-2
|
||||
|
||||
parameters:
|
||||
- name: buildConfigurations
|
||||
@@ -76,7 +76,7 @@ extends:
|
||||
NODE_OPTIONS: --max_old_space_size=16384
|
||||
IsPipeline: 1 # The installer uses this to detect whether it should pick up localizations
|
||||
SkipCppCodeAnalysis: 1 # Skip the code analysis to speed up release CI. It runs on PR CI, anyway
|
||||
IsExperimentationLive: 1 # The build and installer use this to turn on experimentation
|
||||
# IsExperimentationLive: 1 # The build and installer use this to turn on experimentation
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
<UsePrecompiledHeaders Condition="'$(TF_BUILD)' != ''">false</UsePrecompiledHeaders>
|
||||
|
||||
<!-- Change this to bust the cache -->
|
||||
<MSBuildCacheCacheUniverse Condition="'$(MSBuildCacheCacheUniverse)' == ''">202310210737</MSBuildCacheCacheUniverse>
|
||||
<MSBuildCacheCacheUniverse Condition="'$(MSBuildCacheCacheUniverse)' == ''">202407100737</MSBuildCacheCacheUniverse>
|
||||
|
||||
<!--
|
||||
Visual Studio telemetry reads various ApplicationInsights.config files and other files after the project is finished, likely in a detached process.
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
||||
<PackageVersion Include="UnitsNet" Version="4.145.0" />
|
||||
<PackageVersion Include="UnitsNet" Version="5.50.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
|
||||
<PackageVersion Include="Vanara.PInvoke.User32" Version="3.4.11" />
|
||||
<PackageVersion Include="Vanara.PInvoke.Shell32" Version="3.4.11" />
|
||||
@@ -98,4 +98,4 @@
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Client" Version="2.4.17140001" />
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Contract" Version="3.0.16990001" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1365,7 +1365,7 @@ EXHIBIT A -Mozilla Public License.
|
||||
- System.ServiceProcess.ServiceController 8.0.0
|
||||
- System.Text.Encoding.CodePages 8.0.0
|
||||
- UnicodeInformation 2.6.0
|
||||
- UnitsNet 4.145.0
|
||||
- UnitsNet 5.50.0
|
||||
- UTF.Unknown 2.5.1
|
||||
- Vanara.PInvoke.Shell32 3.4.11
|
||||
- Vanara.PInvoke.User32 3.4.11
|
||||
|
||||
831
PowerToys.sln
831
PowerToys.sln
File diff suppressed because it is too large
Load Diff
195
README.md
195
README.md
@@ -41,19 +41,19 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
Go to the [Microsoft PowerToys GitHub releases page][github-release-link] and click on `Assets` at the bottom to show the files available in the release. Please use the appropriate PowerToys installer that matches your machine's architecture and install scope. For most, it is `x64` and per-user.
|
||||
|
||||
<!-- items that need to be updated release to release -->
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.82%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=project%3Amicrosoft%2FPowerToys%2F54
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.81.0/PowerToysUserSetup-0.81.0-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.81.0/PowerToysUserSetup-0.81.0-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.81.0/PowerToysSetup-0.81.0-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.81.0/PowerToysSetup-0.81.0-arm64.exe
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.83%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.82%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.0/PowerToysUserSetup-0.82.0-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.0/PowerToysUserSetup-0.82.0-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.0/PowerToysSetup-0.82.0-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.0/PowerToysSetup-0.82.0-arm64.exe
|
||||
|
||||
| Description | Filename | sha256 hash |
|
||||
|----------------|----------|-------------|
|
||||
| Per user - x64 | [PowerToysUserSetup-0.81.0-x64.exe][ptUserX64] | E62B1EE81954A75355C04E7567B1C9AAD6034AA0C61AD22587F8746D0DC488C8 |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.81.0-arm64.exe][ptUserArm64] | 75330A2DB4F9EF9B548B3B58F8BF3262C8C67E680042639BBBBC87EA244F24E2 |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.81.0-x64.exe][ptMachineX64] | 29F151B01FE3C94D4FD75F2D6E8F09A6C0F0962385B83A5A733F6717312F639D |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.81.0-arm64.exe][ptMachineArm64] | FCE636220E1FB854771258D9558E07B7532728AD4C722A7920338DEE60DEECF7 |
|
||||
| Per user - x64 | [PowerToysUserSetup-0.82.0-x64.exe][ptUserX64] | 295E2A4622C7E347D3E1BAEA6B36BECC328B566496678F1F87DE3F8A12A7F89A |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.82.0-arm64.exe][ptUserArm64] | 55D25D068C6148F0A15C7806B9F813224ABA9C461943F42BB2A8B0E22D28240C |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.82.0-x64.exe][ptMachineX64] | 01B59C00BB43C25BEFEF274755875717AB4DEAB57C0354AB96CF5B1DA4837C9A |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.82.0-arm64.exe][ptMachineArm64] | 1F642B50962516127793C4D3556BF4FC24B9738BAC2F362CAA3BFF8B0C3AF97F |
|
||||
|
||||
This is our preferred method.
|
||||
|
||||
@@ -99,155 +99,134 @@ For guidance on developing for PowerToys, please read the [developer docs](/doc/
|
||||
|
||||
Our [prioritized roadmap][roadmap] of features and utilities that the core team is focusing on.
|
||||
|
||||
### 0.81 - Build 2024 Update
|
||||
### 0.82 - June 2024 Update
|
||||
|
||||
In this release, we focused on new features, stability and improvements.
|
||||
In this release, we focused on stability and improvements.
|
||||
|
||||
**Highlights**
|
||||
|
||||
- New utility: Advanced Paste - This is an evolution based on feedback of the Paste As Plain Text utility to do more. It can paste as plain text, markdown, or json directly with the new UX or with a direct keystroke invoke. These are fully locally executed. In addition, it now has an AI powered option as well if you wish with the free form text box. The AI feature is 100% opt-in and requires an Open AI key. This new system will allow us to have more freedom in the future to quickly add in new features like pasting an image directly to a file or handle additional meta data types past just text.
|
||||
- Thanks [@craigloewen-msft](https://github.com/craigloewen-msft) for the core functionality and [@niels9001](https://github.com/niels9001) for the UI/UX design!
|
||||
- Command Not Found now uses the PowerShell Gallery release and now supports ARM64. Thanks [@carlos-zamora](https://github.com/carlos-zamora)!
|
||||
- Fixed most accessibility issues opened after the latest accessibility review.
|
||||
- Refactored, packaged and released the main Environment Variables Editor, Hosts File Editor and Registry Preview utilities functionality as controls to be integrated into DevHome. Thanks [@dabhattimsft](https://github.com/dabhattimsft) for validating and integrating into DevHome!
|
||||
|
||||
### General
|
||||
|
||||
- Fixed crashes on older CPUS by updating .NET to 8.0.4. (This was a hotfix for 0.80)
|
||||
- New feature added to PowerRename to allow using sequences of random characters and UUIDs when renaming files. Thanks [@jhirvioja](https://github.com/jhirvioja)!
|
||||
- Improvements in the Paste As JSON feature to better handle other CSV delimiters and converting from ini files. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed UI issues that were reported after upgrading to WPF UI on Color Picker and PowerToys Run.
|
||||
- Bug fixes and stability.
|
||||
|
||||
### Advanced Paste
|
||||
|
||||
- New utility: Advanced Paste - This is an evolution based on feedback of the Paste As Plain Text utility to do more. It can paste as plain text, markdown, or json directly with the new UX or with a direct keystroke invoke. These are fully locally executed. In addition, it now has an AI powered option as well if you wish with the free form text box. The AI feature is 100% opt-in and requires an Open AI key. This new system will allow us to have more freedom in the future to quickly add in new features like pasting an image directly to a file or handle additional meta data types past just text.
|
||||
- Thanks [@craigloewen-msft](https://github.com/craigloewen-msft) for the core functionality and [@niels9001](https://github.com/niels9001) for the UI/UX design!
|
||||
|
||||
### AlwaysOnTop
|
||||
|
||||
- Enable border anti-aliasing. Thanks [@ewancg](https://github.com/ewancg)!
|
||||
- Fixed an issue causing external applications triggering Advanced Paste. (This was a hotfix for 0.81)
|
||||
- Added a GPO rule to disallow using online models in Advanced Paste. (This was a hotfix for 0.81)
|
||||
- Improved CSV delimiter handling and plain text parsing for the Paste as JSON feature. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added support to convert from ini in the Paste as JSON feature. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed a memory leak caused by images not being properly cleaned out from clipboard history.
|
||||
- Added an option to hide the UI when it loses focus. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Improved telemetry to get better data about token usage and if clipboard history is a popular feature. Thanks [@craigloewen-msft](https://github.com/craigloewen-msft)!
|
||||
|
||||
### Color Picker
|
||||
|
||||
- Improved accessibility by making the Settings and Copy to clipboard buttons focusable.
|
||||
- Improved accessibility by supporting picking a color using the keyboard.
|
||||
- Fixed the opaque background corners in the picker that were introduced after the upgrade to WPFUI.
|
||||
|
||||
### Command Not Found
|
||||
### Developer Files Preview (Monaco)
|
||||
|
||||
- Upgraded the Command Not Found to use the new PowerShell Gallery release and support ARM64. Thanks [@carlos-zamora](https://github.com/carlos-zamora)!
|
||||
- Improved the syntax highlight for .gitignore files. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Checking for the sticky scroll option in code behind was being done twice. Removed one of the checks. Thanks [@downarowiczd](https://github.com/downarowiczd)!
|
||||
|
||||
### Environment Variables Editor
|
||||
|
||||
- Refactored, packaged and released the main Environment Variables Editor functionality as a control to be integrated into DevHome. Thanks [@dabhattimsft](https://github.com/dabhattimsft) for validating and integrating into DevHome!
|
||||
|
||||
### FancyZones
|
||||
|
||||
- Fixed window wrap around behavior when overriding Windows key and arrow shortcuts on single monitor scenarios. Thanks [@DanRosenberry](https://github.com/DanRosenberry)!
|
||||
- Improved accessibility of the editor by listing the keyboard shortcuts in the Canvas Editor.
|
||||
- Added clarity to the UI section tooltips. Thanks [@anson-poon](https://github.com/anson-poon)!
|
||||
|
||||
### File Explorer add-ons
|
||||
|
||||
- Updated Monaco to 0.47 and added the new sticky scroll setting for DevFiles viewer. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Added the new font size setting for DevFiles viewer. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Added support for .srt (subtitle) file previewing in DevFiles viewer. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Fixed a crash when the preview handlers received a 64-bit handle from the OS. Thanks [@z4pf1sh](https://github.com/z4pf1sh)!
|
||||
- Fixed a crash when trying to update window bounds and File Explorer already disposed the preview.
|
||||
|
||||
### Find My Mouse
|
||||
|
||||
- Added the option to have to use the Windows + Control keys to activate. Thanks [@Gentoli](https://github.com/Gentoli)!
|
||||
|
||||
### Hosts File Editor
|
||||
|
||||
- Refactored, packaged and released the main Hosts File Editor functionality as a control to be integrated into DevHome. Thanks [@dabhattimsft](https://github.com/dabhattimsft) for validating and integrating into DevHome!
|
||||
|
||||
### Image Resizer
|
||||
|
||||
- Supported narrator announcing the checkboxes in the UI and the sizes combobox. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Improved accessibility by increasing contrast in the text color of combobox items.
|
||||
- Improved spacing definitions in the UI so that hosts name are not hidden when resizing and icons are well aligned. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Changed the additional lines dialog to show the horizontal scrollbar instead of wrapping contents. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Improved the duplication check's logic to improve performance and take into account features that were introduced after it. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
|
||||
### Installer
|
||||
|
||||
- Fixed some install failures when the folders the DSC module is to be installed in isn't accessible by the WiX installer. (This was a hotfix for 0.80)
|
||||
- Detecting install location for DSC now uses registry instead of WMI to improve performance. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed an error causing the machine scope installer to not install correctly in machines where the documents folder is in a UNC network path. We're still working in a fix for the user scope installer.
|
||||
|
||||
### Keyboard Manager
|
||||
|
||||
- Fixed startup crashes in the editor when the Visual C++ Redistributable wasn't installed. (This was a hotfix for 0.80)
|
||||
- Fixed an accessibility issue where the first button wasn't focused after adding a new row in the editor.
|
||||
- Environment Variables are now expanded in arguments of programs started through a shortcut. Thanks [@HydroH](https://github.com/HydroH)!
|
||||
|
||||
### Paste as Plain Text
|
||||
|
||||
- Paste as Plain Text was removed as a separate utility, since its functionality is now part of the Advanced Paste utility.
|
||||
- Fixed the remaining install failures when the folders the DSC module is to be installed in isn't accessible by the WiX installer for user scope installations.
|
||||
- Fixed an issue causing ARM 64 uninstall process to not correctly finding powershell 7 to run uninstall scripts.
|
||||
|
||||
### Peek
|
||||
|
||||
- Updated icons, tweaked UI and refactored internal code. Thanks [@Jay-o-Way](https://github.com/Jay-o-Way)!
|
||||
- Updated Monaco to 0.47 and added the new sticky scroll setting for DevFiles viewer. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Added the new font size setting for DevFiles viewer. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Upgrade the SharpCompress dependency to 0.37.2 and fixed archive parsing. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed aliasing in the image viewer.
|
||||
- Added support for .srt (subtitle) file previewing in DevFiles viewer. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Prevent activating Peek when the user is renaming a file. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Added support to preview special folders like Recycle Bin and My PC instead of throwing an error.
|
||||
- Fixed a crash caused by double releasing a COM object from the module interface.
|
||||
|
||||
### Power Rename
|
||||
|
||||
- Fixed the descriptions that were mixed up in the regex helper (\S and \w).
|
||||
- Improved apostrophe character handling for the Capitalize and Titlecase renaming flags. Thanks [@anthonymonforte](https://github.com/anthonymonforte)!
|
||||
- Added a feature to allow using sequences of random characters or UUIDs when renaming files. Thanks [@jhirvioja](https://github.com/jhirvioja)!
|
||||
|
||||
### PowerToys Run
|
||||
|
||||
- Added support for UNC paths starting with // in the Folder plugin. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed the plugin load failed message to list the failed plugins. Thanks [@belkiss](https://github.com/belkiss)!
|
||||
- Icons for MSIX packages are now updated when a package update is detected. Thanks [@HydroH](https://github.com/HydroH)!
|
||||
- Use Mica backdrop instead of Acrylic to fix random crashes caused by the Windows composition being momentarily turned off.
|
||||
- Improved accessibility in the results list action buttons by improving contrast of hovered/focused buttons.
|
||||
- Improved the plugin descriptions for consistency in the UI. Thanks [@HydroH](https://github.com/HydroH)!
|
||||
- Fixed UI scaling for different dpi scenarios.
|
||||
- Fixed crash on a racing condition when updating UWP icon paths in the Program plugin. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed PowerToys Run hanging when trying to close an unresponsive window in the WindowWalker plugin. Thanks [@GhostVaibhav](https://github.com/GhostVaibhav)!
|
||||
- Fixed the example in the UnitConverter description to reduce confusion with the inches abbreviation (now uses "to" instead of "in"). Thanks [@acekirkpatrick](https://github.com/acekirkpatrick)!
|
||||
- Brought the acrylic background back and applied a proper fix to the titlebar accent showing through transparency.
|
||||
- Fixed an issue causing the transparency from the UI disappearing after some time.
|
||||
|
||||
### Quick Accent
|
||||
|
||||
- Added support for the Esperanto character set. Thanks [@salutontalk](https://github.com/salutontalk) and [@ccmywish](https://github.com/ccmywish)!
|
||||
- Added the ǽ and ϑ characters. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Added support for the Crimean Tatar character set. Thanks [@cor-bee](https://github.com/cor-bee)!
|
||||
- Added the Numero symbol and double acute accent character. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Added the International Phonetic Alphabet characters. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Fixed the character description center positioning. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Added feminine and masculine ordinal indicator characters to the Portuguese character set. Thanks [@octastylos-pseudodipteros](https://github.com/octastylos-pseudodipteros)!
|
||||
|
||||
### Registry Preview
|
||||
### Screen Ruler
|
||||
|
||||
- Refactored, packaged and released the main Registry Preview functionality as a control to be integrated into DevHome. Thanks [@dabhattimsft](https://github.com/dabhattimsft) for validating and integrating into DevHome!
|
||||
|
||||
### Text Extractor
|
||||
|
||||
- Fixed an issue causing the Settings page to not be opened when clicking the Settings button in Text Extractor's overlay. (This was a hotfix for 0.80)
|
||||
- Updated the default activation hotkey to Win+Control+Shift+M, in order to not conflict with the Windows shortcut that restores minimized windows (Win+Shift+M). Thanks [@nx-frost](https://github.com/nx-frost)!
|
||||
|
||||
### Settings
|
||||
|
||||
- Improved UI ordering of the File Explorer add-ons. Thanks [@niels9001](https://github.com/niels9001)!
|
||||
- Applied fixes to theme overriding and cleaned up unneeded code. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed misspells in references to the Hosts File Editor utility. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Improved accessibility of the Select Folder button in the Settings Backup UI.
|
||||
- Improved accessibility by improving focus and tab navigation in the ColorPicker page. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Added a description to the fallback encoder setting in the Image Resizer page. Thanks [@Kissaki](https://github.com/Kissaki)!
|
||||
- Refactored and improved performance in the PowerToys Run plugins UI in the Settings page. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed a crash when a user cleared the contents of a Number Box in the PowerToys Run plugins additional options. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Update the PATH environment variables with the user scope PATH when entering the Command Not Found page to improve PowerShell detection.
|
||||
- Disabled the UI to enable/disable clipboard history in the Advanced Paste settings page when clipboard history is disabled by GPO in the system. (This was a hotfix for 0.81)
|
||||
- Updated Advanced Paste's Settings and OOBE page to clarify that the AI use is optional and opt-in. (This was a hotfix for 0.81)
|
||||
- Corrected a spelling fix in Advanced Paste's settings page. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added localization support for the "Configure OpenAI Key" button in Advanced Paste's settings page. Thanks [@zetaloop](https://github.com/zetaloop)!
|
||||
- Fixed extra GPO warnings being shown in Advanced Paste's settings page even if the module is disabled. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed a crash when a PowerToys Run plugin icon path is badly formed.
|
||||
- Disabled the experimentation paths in code behind to improve performance, since there's no current experimentation going on.
|
||||
|
||||
### Documentation
|
||||
|
||||
- Added the WebSearchShortcut plugin to PowerToys Run thirdPartyRunPlugins.md docs. Thanks [@Daydreamer-riri](https://github.com/Daydreamer-riri)!
|
||||
- Updated COMMUNITY.md with the project managers that are part of the core team.
|
||||
- Improved the DSC samples.
|
||||
- Added the 1Password plugin to PowerToys Run thirdPartyRunPlugins.md docs. Thanks [@KairuDeibisu](https://github.com/KairuDeibisu)!
|
||||
- Added the UnicodeInput plugin to PowerToys Run thirdPartyRunPlugins.md docs. Thanks [@nathancartlidge](https://github.com/nathancartlidge)!
|
||||
- Adjusted the readme and release notes to clarify use of AI on Advanced Paste. (This was a hotfix for 0.81)
|
||||
- Added the Edge Workspaces plugin to PowerToys Run thirdPartyRunPlugins.md docs. Thanks [@quachpas](https://github.com/quachpas)!
|
||||
- Removed the deprecated Guid plugin from PowerToys Run thirdPartyRunPlugins.md docs. Thanks [@abduljawada](https://github.com/abduljawada)!
|
||||
- Added the PowerHexInspector plugin to PowerToys Run thirdPartyRunPlugins.md docs. Thanks [@NaroZeol](https://github.com/NaroZeol)!
|
||||
- Fixed a broken link in the communication-with-modules.md file. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Updated COMMUNITY.md with missing and former members.
|
||||
|
||||
### Development
|
||||
|
||||
- Updated System.Drawing.Common to 8.0.5 to fix CI builds after the .NET 8.0.5 upgrade was released.
|
||||
- Fixed file permissions when doing a build using cache on PR CI. Thanks [@dfederm](https://github.com/dfederm)!
|
||||
- Removed the Test SDK reference on ARM64 to fix local building for ARM64. Thanks [@dfederm](https://github.com/dfederm)!
|
||||
- Replaced make_pair with RemapBufferRow in Keyboard Manager internal code. Thanks [@masaru-iritani](https://github.com/masaru-iritani)!
|
||||
- Added CODEOWNERS file to protect sensitive parts of the repo. Thanks [@htcfreek](https://github.com/htcfreek) for the help in figuring out how to make the spellcheck folder an exception!
|
||||
- Added comments in code. to make it clear what the error badge in PowerToys Run plugin list in Settings means. Thanks [@Jay-o-Way](https://github.com/Jay-o-Way)!
|
||||
- Enabled caching by default in the PR CI pipelines. Thanks [@dfederm](https://github.com/dfederm)!
|
||||
- Disabled caching for PR started from forks, since those were failing. Thanks [@dfederm](https://github.com/dfederm)!
|
||||
- Removed baseline files for policy checking and turned on the "TSA" process in the release pipelines instead.
|
||||
- Added caching of nuget packages in the PR CI pipelines. Thanks [@dfederm](https://github.com/dfederm)!
|
||||
- Updated the release CI pipelines TouchdownBuildTask to v3.
|
||||
- Moved the release CI pipelines to ESRPv5.
|
||||
- Added a policy for GitHub Copilot Workspaces for the repo on GitHub. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Fixed ci UI tests to point to the correct Visual Studio vstest location after a Visual Studio upgrade. (This was a hotfix for 0.81)
|
||||
- Updated System.Drawing.Common to 8.0.6 to fix CI builds after the .NET 8.0.6 upgrade was released.
|
||||
- Removed an incorrect file reference to long removed documentation from the solution file. Thanks [@Kissaki](https://github.com/Kissaki)!
|
||||
- Upgraded Windows App SDK to 1.5.3.
|
||||
- Removed use of the BinaryFormatter API from Mouse Without Borders, which is expected to be deprecated in .NET 9.
|
||||
- The user scope installer is now sent to the Microsoft store instead of the machine scope installer.
|
||||
- Refactored Mouse Jump's internal code to allow for a future introduction of customizable appearance features. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
- Removed a noisy error from spell check ci runs.
|
||||
- Improved the ci agent pool selection code.
|
||||
- Updated Xamlstyler.console to 3.2404.2. Thanks [@Jvr2022](https://github.com/Jvr2022)!
|
||||
- Updated UnitsNet to 5.50.0 Thanks [@Jvr2022](https://github.com/Jvr2022)!
|
||||
- Replaced LPINPUT with std::vector of INPUT instances in Keyboard Manager internal code. Thanks [@masaru-iritani](https://github.com/masaru-iritani)!
|
||||
- Improved the Microsoft Store submission ci action to use the proper cli and authentication.
|
||||
|
||||
#### What is being planned for version 0.82
|
||||
#### What is being planned for version 0.83
|
||||
|
||||
For [v0.82][github-next-release-work], we'll work on the items below:
|
||||
For [v0.83][github-next-release-work], we'll work on the items below:
|
||||
|
||||
- Stability / bug fixes
|
||||
- New utility: Dev Projects
|
||||
- Language selection
|
||||
- New module: File Actions Menu
|
||||
|
||||
|
||||
@@ -47,7 +47,16 @@ registerAdditionalNewLanguage("id", [".fileExtension"], idDefinition(), monaco)
|
||||
|
||||
* The id can be anything. Recommended is one of the file extensions. For example "php" or "reg".
|
||||
|
||||
4. Execute the steps described in the [monaco_languages.json](#monaco_languagesjson) section.
|
||||
4. In case you wish to add a custom color for a token, you can do so by adding the following line to [`customTokenColors.js`](/src/common/FilePreviewCommon/Assets/Monaco/customTokenColors.js):
|
||||
```javascript
|
||||
{token: 'token-name', foreground: 'ff0000'}
|
||||
```
|
||||
> Replace `token-name` with the name of the token and `ff0000` with the hex code of the desired color.
|
||||
> Note: you can also specify a `background` and a `fontStyle` attribute for your token.
|
||||
|
||||
* Keep in mind that these rules apply to all languages. Therefore, you should not change the colors of any default tokens. Instead, create new tokens specific to the language you are adding.
|
||||
|
||||
5. Execute the steps described in the [monaco_languages.json](#monaco_languagesjson) section.
|
||||
|
||||
### Add a new file extension to an existing language
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ In order to test the remapping logic, a mocked keyboard input handler had to be
|
||||
The [`MockedInput`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/MockedInput.h) class uses a 256 size `bool` vector to store the key state for each key code. Identifying the foreground process is mocked by simply setting and getting a string value for the name of the current process.
|
||||
|
||||
[To mock the `SendInput` method](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/test/MockedInput.cpp#L10-L110), the steps for processing the input are as follows. This implementation is based on public documentation for SendInput and the behavior of key messages and keyboard hooks:
|
||||
- Iterate over all the inputs in the INPUT array argument
|
||||
- Iterate over all the inputs in the `INPUT` vector argument.
|
||||
- If the event is a key up event, then it is considered [`WM_SYSKEYUP`](https://learn.microsoft.com/windows/win32/inputdev/wm-syskeyup) if Alt is held down, otherwise it is `WM_KEYUP`.
|
||||
- If the event is a key down event, then it is considered [`WM_SYSKEYDOWN`](https://learn.microsoft.com/windows/win32/inputdev/wm-syskeydown) if either Alt is held down or if it is F10, otherwise it is `WM_KEYDOWN`.
|
||||
- An optional function which can be set on the `MockedInput` handler can be used to test for the number of times a key event is received by the system with a particular condition using [`sendVirtualInputCallCondition`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/test/MockedInput.cpp#L48-L52).
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
<?define AdvancedPasteProjectName="AdvancedPaste"?>
|
||||
<?define RegistryPreviewProjectName="RegistryPreview"?>
|
||||
<?define PeekProjectName="Peek"?>
|
||||
<?define ProjectsProjectName="Projects"?>
|
||||
|
||||
<?define RepoDir="$(var.ProjectDir)..\..\" ?>
|
||||
<?if $(var.Platform) = x64?>
|
||||
|
||||
@@ -449,15 +449,6 @@
|
||||
</RegistryKey>
|
||||
<File Id="PowerOCR_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\$(var.Language)\PowerToys.PowerOCR.resources.dll" />
|
||||
</Component>
|
||||
<Component
|
||||
Id="ProjectsEditor_$(var.IdSafeLanguage)_Component"
|
||||
Directory="Resource$(var.IdSafeLanguage)INSTALLFOLDER"
|
||||
Guid="$(var.CompGUIDPrefix)21">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="ProjectsEditor_$(var.IdSafeLanguage)_Component" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Id="ProjectsEditor_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\$(var.Language)\PowerToys.ProjectsEditor.resources.dll" />
|
||||
</Component>
|
||||
<?undef IdSafeLanguage?>
|
||||
<?undef CompGUIDPrefix?>
|
||||
<?endforeach?>
|
||||
|
||||
@@ -21,7 +21,7 @@ $fileWxs = Get-Content $wxsFilePath;
|
||||
|
||||
$fileExclusionList = @("*.pdb", "*.lastcodeanalysissucceeded", "createdump.exe", "powertoys.exe")
|
||||
|
||||
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "monacoSpecialLanguages.js", "*.pri")
|
||||
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "monacoSpecialLanguages.js", "customTokenColors.js", "*.pri")
|
||||
|
||||
$dllsToIgnore = @("System.CodeDom.dll", "WindowsBase.dll")
|
||||
|
||||
|
||||
@@ -357,7 +357,7 @@ UINT __stdcall InstallDSCModuleCA(MSIHANDLE hInstall)
|
||||
ExitOnFailure(hr, "Unable to determine Powershell modules path");
|
||||
}
|
||||
|
||||
const auto modulesPath = baseModulesPath / L"Microsoft.PowerToys.Configure" / get_product_version();
|
||||
const auto modulesPath = baseModulesPath / L"Microsoft.PowerToys.Configure" / get_product_version(false);
|
||||
|
||||
std::error_code errorCode;
|
||||
fs::create_directories(modulesPath, errorCode);
|
||||
@@ -411,7 +411,7 @@ UINT __stdcall UninstallDSCModuleCA(MSIHANDLE hInstall)
|
||||
}
|
||||
|
||||
const auto powerToysModulePath = baseModulesPath / L"Microsoft.PowerToys.Configure";
|
||||
const auto versionedModulePath = powerToysModulePath / get_product_version();
|
||||
const auto versionedModulePath = powerToysModulePath / get_product_version(false);
|
||||
|
||||
std::error_code errorCode;
|
||||
|
||||
@@ -1223,7 +1223,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
}
|
||||
processes.resize(bytes / sizeof(processes[0]));
|
||||
|
||||
std::array<std::wstring_view, 35> processesToTerminate = {
|
||||
std::array<std::wstring_view, 32> processesToTerminate = {
|
||||
L"PowerToys.PowerLauncher.exe",
|
||||
L"PowerToys.Settings.exe",
|
||||
L"PowerToys.AdvancedPaste.exe",
|
||||
@@ -1255,9 +1255,6 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
L"PowerToys.MouseWithoutBordersService.exe",
|
||||
L"PowerToys.CropAndLock.exe",
|
||||
L"PowerToys.EnvironmentVariables.exe",
|
||||
L"PowerToys.ProjectsSnapshotTool.exe",
|
||||
L"PowerToys.ProjectsLauncher.exe",
|
||||
L"PowerToys.ProjectsEditor.exe",
|
||||
L"PowerToys.exe",
|
||||
};
|
||||
|
||||
|
||||
@@ -12,5 +12,10 @@ namespace Common.UI
|
||||
{
|
||||
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= 22000;
|
||||
}
|
||||
|
||||
public static bool IsGreaterThanWindows11_21H2()
|
||||
{
|
||||
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build > 22000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace Common.UI
|
||||
EnvironmentVariables,
|
||||
Dashboard,
|
||||
AdvancedPaste,
|
||||
Projects,
|
||||
}
|
||||
|
||||
private static string SettingsWindowNameToString(SettingsWindow value)
|
||||
@@ -78,8 +77,6 @@ namespace Common.UI
|
||||
return "Dashboard";
|
||||
case SettingsWindow.AdvancedPaste:
|
||||
return "AdvancedPaste";
|
||||
case SettingsWindow.Projects:
|
||||
return "Projects";
|
||||
default:
|
||||
{
|
||||
return string.Empty;
|
||||
|
||||
@@ -24,18 +24,15 @@
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>..\..\..\;..\..\common;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="DisplayUtils.h" />
|
||||
<ClInclude Include="MonitorEnumerator.h" />
|
||||
<ClInclude Include="monitors.h" />
|
||||
<ClInclude Include="dpi_aware.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="DisplayUtils.cpp" />
|
||||
<ClCompile Include="monitors.cpp" />
|
||||
<ClCompile Include="dpi_aware.cpp" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
#include "DisplayUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include <dpi_aware.h>
|
||||
#include <MonitorEnumerator.h>
|
||||
|
||||
#include <utils/OnThreadExecutor.h>
|
||||
|
||||
namespace DisplayUtils
|
||||
{
|
||||
constexpr bool not_digit(wchar_t ch)
|
||||
{
|
||||
return '0' <= ch && ch <= '9';
|
||||
}
|
||||
|
||||
std::wstring remove_non_digits(const std::wstring& input)
|
||||
{
|
||||
std::wstring result;
|
||||
std::copy_if(input.begin(), input.end(), std::back_inserter(result), not_digit);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::pair<std::wstring, std::wstring> SplitDisplayDeviceId(const std::wstring& str) noexcept
|
||||
{
|
||||
// format: \\?\DISPLAY#{device id}#{instance id}#{some other id}
|
||||
// example: \\?\DISPLAY#GSM1388#4&125707d6&0&UID8388688#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
|
||||
// output: { GSM1388, 4&125707d6&0&UID8388688 }
|
||||
|
||||
size_t nameStartPos = str.find_first_of('#');
|
||||
size_t uidStartPos = str.find('#', nameStartPos + 1);
|
||||
size_t uidEndPos = str.find('#', uidStartPos + 1);
|
||||
|
||||
if (nameStartPos == std::string::npos || uidStartPos == std::string::npos || uidEndPos == std::string::npos)
|
||||
{
|
||||
return { str, L"" };
|
||||
}
|
||||
|
||||
return { str.substr(nameStartPos + 1, uidStartPos - nameStartPos - 1), str.substr(uidStartPos + 1, uidEndPos - uidStartPos - 1) };
|
||||
}
|
||||
|
||||
std::pair<bool, std::vector<DisplayUtils::DisplayData>> GetDisplays()
|
||||
{
|
||||
bool success = true;
|
||||
std::vector<DisplayUtils::DisplayData> result{};
|
||||
auto allMonitors = MonitorEnumerator::Enumerate();
|
||||
|
||||
OnThreadExecutor dpiUnawareThread;
|
||||
dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] {
|
||||
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
|
||||
SetThreadDpiHostingBehavior(DPI_HOSTING_BEHAVIOR_MIXED);
|
||||
} }).wait();
|
||||
|
||||
for (auto& monitorData : allMonitors)
|
||||
{
|
||||
MONITORINFOEX monitorInfo = monitorData.second;
|
||||
MONITORINFOEX dpiUnawareMonitorInfo{};
|
||||
|
||||
dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] {
|
||||
dpiUnawareMonitorInfo.cbSize = sizeof(dpiUnawareMonitorInfo);
|
||||
if (!GetMonitorInfo(monitorData.first, &dpiUnawareMonitorInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
} }).wait();
|
||||
|
||||
UINT dpi = 0;
|
||||
if (DPIAware::GetScreenDPIForMonitor(monitorData.first, dpi) != S_OK)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
DisplayUtils::DisplayData data{
|
||||
.monitor = monitorData.first,
|
||||
.dpi = dpi,
|
||||
.monitorRectDpiAware = monitorInfo.rcMonitor,
|
||||
.monitorRectDpiUnaware = dpiUnawareMonitorInfo.rcMonitor,
|
||||
};
|
||||
|
||||
bool foundActiveMonitor = false;
|
||||
DISPLAY_DEVICE displayDevice{ .cb = sizeof(displayDevice) };
|
||||
DWORD displayDeviceIndex = 0;
|
||||
while (EnumDisplayDevicesW(monitorInfo.szDevice, displayDeviceIndex, &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
|
||||
{
|
||||
/*
|
||||
* if (WI_IsFlagSet(displayDevice.StateFlags, DISPLAY_DEVICE_ACTIVE) &&
|
||||
WI_IsFlagClear(displayDevice.StateFlags, DISPLAY_DEVICE_MIRRORING_DRIVER))
|
||||
*/
|
||||
if (((displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE) == DISPLAY_DEVICE_ACTIVE) &&
|
||||
(displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0)
|
||||
{
|
||||
// Find display devices associated with the display.
|
||||
foundActiveMonitor = true;
|
||||
break;
|
||||
}
|
||||
|
||||
displayDeviceIndex++;
|
||||
}
|
||||
|
||||
if (foundActiveMonitor)
|
||||
{
|
||||
auto deviceId = SplitDisplayDeviceId(displayDevice.DeviceID);
|
||||
data.id = deviceId.first;
|
||||
data.instanceId = deviceId.second;
|
||||
try
|
||||
{
|
||||
std::wstring numberStr = displayDevice.DeviceName; // \\.\DISPLAY1\Monitor0
|
||||
numberStr = numberStr.substr(0, numberStr.find_last_of('\\')); // \\.\DISPLAY1
|
||||
numberStr = remove_non_digits(numberStr);
|
||||
data.number = std::stoi(numberStr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
|
||||
// Use the display name as a fallback value when no proper device was found.
|
||||
data.id = monitorInfo.szDevice;
|
||||
data.instanceId = L"";
|
||||
|
||||
try
|
||||
{
|
||||
std::wstring numberStr = monitorInfo.szDevice; // \\.\DISPLAY1
|
||||
numberStr = remove_non_digits(numberStr);
|
||||
data.number = std::stoi(numberStr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.push_back(data);
|
||||
}
|
||||
|
||||
return { success, result };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace DisplayUtils
|
||||
{
|
||||
struct DisplayData
|
||||
{
|
||||
HMONITOR monitor{};
|
||||
std::wstring id;
|
||||
std::wstring instanceId;
|
||||
unsigned int number{};
|
||||
unsigned int dpi{};
|
||||
RECT monitorRectDpiAware{};
|
||||
RECT monitorRectDpiUnaware{};
|
||||
};
|
||||
|
||||
std::pair<bool, std::vector<DisplayData>> GetDisplays();
|
||||
};
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <Windows.h>
|
||||
|
||||
class MonitorEnumerator
|
||||
{
|
||||
public:
|
||||
static std::vector<std::pair<HMONITOR, MONITORINFOEX>> Enumerate()
|
||||
{
|
||||
MonitorEnumerator inst;
|
||||
EnumDisplayMonitors(NULL, NULL, Callback, reinterpret_cast<LPARAM>(&inst));
|
||||
return inst.m_monitors;
|
||||
}
|
||||
|
||||
private:
|
||||
MonitorEnumerator() = default;
|
||||
~MonitorEnumerator() = default;
|
||||
|
||||
static BOOL CALLBACK Callback(HMONITOR monitor, HDC /*hdc*/, LPRECT /*pRect*/, LPARAM param)
|
||||
{
|
||||
MonitorEnumerator* inst = reinterpret_cast<MonitorEnumerator*>(param);
|
||||
MONITORINFOEX mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
if (GetMonitorInfo(monitor, &mi))
|
||||
{
|
||||
inst->m_monitors.push_back({monitor, mi});
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
std::vector<std::pair<HMONITOR, MONITORINFOEX>> m_monitors;
|
||||
};
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "dpi_aware.h"
|
||||
|
||||
#include "monitors.h"
|
||||
#include <ShellScalingApi.h>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
|
||||
namespace DPIAware
|
||||
{
|
||||
@@ -62,24 +60,6 @@ namespace DPIAware
|
||||
}
|
||||
}
|
||||
|
||||
void Convert(HMONITOR monitor_handle, RECT& rect)
|
||||
{
|
||||
if (monitor_handle == NULL)
|
||||
{
|
||||
const POINT ptZero = { 0, 0 };
|
||||
monitor_handle = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
|
||||
UINT dpi_x, dpi_y;
|
||||
if (GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y) == S_OK)
|
||||
{
|
||||
rect.left = static_cast<long>(std::round(rect.left * static_cast<float>(dpi_x) / DEFAULT_DPI));
|
||||
rect.right = static_cast<long>(std::round(rect.right * static_cast<float>(dpi_x) / DEFAULT_DPI));
|
||||
rect.top = static_cast<long>(std::round(rect.top * static_cast<float>(dpi_y) / DEFAULT_DPI));
|
||||
rect.bottom = static_cast<long>(std::round(rect.bottom * static_cast<float>(dpi_y) / DEFAULT_DPI));
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertByCursorPosition(float& width, float& height)
|
||||
{
|
||||
HMONITOR targetMonitor = nullptr;
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace DPIAware
|
||||
HRESULT GetScreenDPIForPoint(POINT p, UINT& dpi);
|
||||
HRESULT GetScreenDPIForCursor(UINT& dpi);
|
||||
void Convert(HMONITOR monitor_handle, float& width, float& height);
|
||||
void Convert(HMONITOR monitor_handle, RECT& rect);
|
||||
void ConvertByCursorPosition(float& width, float& height);
|
||||
void InverseConvert(HMONITOR monitor_handle, float& width, float& height);
|
||||
void EnableDPIAwarenessForThisProcess();
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
tokenizer: {
|
||||
root: [
|
||||
[/^#.*$/, 'comment'],
|
||||
[/^\s*!.*/, 'invalid'],
|
||||
[/^\s*[^#]+/, "tag"]
|
||||
[/.*((?<!(^|\/))\*\*.*|\*\*(?!(\/|$))).*/, 'invalid'],
|
||||
[/((?:^!\s*(?:\\\s|\S)+)?)((?:^\s*(?:\\\s|\S)+)?)((?:\s+(?:\\\s|\S)+)*)/, ['custom-gitignore.negation', 'tag', 'invalid']]
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export const customTokenColors = [
|
||||
{token: 'custom-gitignore.negation', foreground: 'c00ce0'}
|
||||
];
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
// Get URL parameters:
|
||||
// `code` contains the code of the file in base64 encoded
|
||||
// `theme` can be "light" or "dark"
|
||||
// `theme` can be "vs" for light theme or "vs-dark" for dark theme
|
||||
// `lang` is the language of the file
|
||||
// `wrap` if the editor is wrapping or not
|
||||
|
||||
@@ -59,19 +59,29 @@
|
||||
<script src="http://[[PT_URL]]/monacoSpecialLanguages.js" type="module"></script>
|
||||
<script type="module">
|
||||
var editor;
|
||||
import { registerAdditionalLanguages } from "http://[[PT_URL]]/monacoSpecialLanguages.js"
|
||||
import { registerAdditionalLanguages } from 'http://[[PT_URL]]/monacoSpecialLanguages.js';
|
||||
import { customTokenColors } from 'http://[[PT_URL]]/customTokenColors.js';
|
||||
require.config({ paths: { vs: 'http://[[PT_URL]]/monacoSRC/min/vs' } });
|
||||
require(['vs/editor/editor.main'], async function () {
|
||||
await registerAdditionalLanguages(monaco)
|
||||
|
||||
// Creates a theme to handle custom tokens
|
||||
monaco.editor.defineTheme('theme', {
|
||||
base: theme, // Sets the base theme to "vs" or "vs-dark" depending on the user's preference
|
||||
inherit: true,
|
||||
rules: customTokenColors,
|
||||
colors: {} // `colors` is a required attribute
|
||||
});
|
||||
|
||||
// Creates the editor
|
||||
// For all parameters: https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.istandaloneeditorconstructionoptions.html
|
||||
// For all parameters: https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IStandaloneEditorConstructionOptions.html
|
||||
editor = monaco.editor.create(document.getElementById('container'), {
|
||||
value: code, // Sets content of the editor
|
||||
language: lang, // Sets language fof the code
|
||||
language: lang, // Sets language of the code
|
||||
readOnly: true, // Sets to readonly
|
||||
theme: theme, // Sets editor theme
|
||||
theme: 'theme', // Sets editor theme
|
||||
minimap: {enabled: false}, // Disables minimap
|
||||
lineNumbersMinChars: "3", //Width of the line numbers
|
||||
lineNumbersMinChars: '3', // Width of the line numbers
|
||||
scrollbar: {
|
||||
// Deactivate shadows
|
||||
shadows: false,
|
||||
@@ -79,17 +89,16 @@
|
||||
// Render scrollbar automatically
|
||||
vertical: 'auto',
|
||||
horizontal: 'auto',
|
||||
|
||||
},
|
||||
stickyScroll: {enabled: stickyScroll},
|
||||
fontSize: fontSize,
|
||||
wordWrap: (wrap?"on":"off") // Word wraps
|
||||
wordWrap: (wrap ? 'on' : 'off') // Word wraps
|
||||
});
|
||||
window.onresize = function (){
|
||||
window.onresize = () => {
|
||||
editor.layout();
|
||||
};
|
||||
|
||||
// Add switch wrap button to context menu
|
||||
// Add toggle wrap button to context menu
|
||||
editor.addAction({
|
||||
id: 'text-wrap',
|
||||
|
||||
@@ -101,17 +110,17 @@
|
||||
// A rule to evaluate on top of the precondition in order to dispatch the keybindings.
|
||||
keybindingContext: null,
|
||||
|
||||
contextMenuGroupId: 'cutcopypaste',
|
||||
contextMenuGroupId: 'cutcopypaste',
|
||||
|
||||
contextMenuOrder: 100,
|
||||
contextMenuOrder: 100,
|
||||
|
||||
// Method that will be executed when the action is triggered.
|
||||
// @param editor The editor instance is passed in as a convenience
|
||||
run: function (ed) {
|
||||
if(wrap){
|
||||
editor.updateOptions({ wordWrap: "off" })
|
||||
}else{
|
||||
editor.updateOptions({ wordWrap: "on" })
|
||||
if (wrap) {
|
||||
editor.updateOptions({ wordWrap: 'off' })
|
||||
} else {
|
||||
editor.updateOptions({ wordWrap: 'on' })
|
||||
}
|
||||
wrap = !wrap;
|
||||
}
|
||||
@@ -120,11 +129,11 @@
|
||||
onContextMenu();
|
||||
});
|
||||
|
||||
function onContextMenu(){
|
||||
function onContextMenu() {
|
||||
// Hide context menu items
|
||||
// Code modified from https://stackoverflow.com/questions/48745208/disable-cut-and-copy-in-context-menu-in-monaco-editor/65413517#65413517
|
||||
let menus = require('vs/platform/actions/common/actions').MenuRegistry._menuItems
|
||||
let contextMenuEntry = [...menus].find(entry => entry[0].id == "EditorContext")
|
||||
let contextMenuEntry = [...menus].find(entry => entry[0].id == 'EditorContext')
|
||||
let contextMenuLinks = contextMenuEntry[1]
|
||||
|
||||
let removableIds = ['editor.action.clipboardCutAction', 'editor.action.formatDocument', 'editor.action.formatSelection', 'editor.action.quickCommand', 'editor.action.quickOutline', 'editor.action.refactor', 'editor.action.sourceAction', 'editor.action.rename', undefined, 'editor.action.revealDefinition', 'editor.action.revealDeclaration', 'editor.action.goToTypeDefinition', 'editor.action.goToImplementation', 'editor.action.goToReferences', 'editor.action.changeAll']
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
<None Update="Assets\Monaco\monacoSpecialLanguages.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\Monaco\customTokenColors.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Include="Assets\Monaco\monacoSRC\**">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "pch.h"
|
||||
#include "pch.h"
|
||||
#include "GPOWrapper.h"
|
||||
#include "GPOWrapper.g.cpp"
|
||||
|
||||
@@ -176,8 +176,4 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteOnlineAIModelsValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredProjectsEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredProjectsEnabledValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include "GPOWrapper.g.h"
|
||||
#include <common/utils/gpo.h>
|
||||
|
||||
@@ -50,7 +50,6 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOnlineAIModelsValue();
|
||||
static GpoRuleConfigured GetConfiguredProjectsEnabledValue();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOnlineAIModelsValue();
|
||||
static GpoRuleConfigured GetConfiguredProjectsEnabledValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,10 +61,5 @@ namespace PowerToys.GPOWrapperProjection
|
||||
{
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetRunPluginEnabledValue(pluginID);
|
||||
}
|
||||
|
||||
public static GpoRuleConfigured GetConfiguredProjectsEnabledValue()
|
||||
{
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredProjectsEnabledValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace ManagedCommon
|
||||
PowerRename,
|
||||
PowerLauncher,
|
||||
PowerAccent,
|
||||
Projects,
|
||||
RegistryPreview,
|
||||
MeasureTool,
|
||||
ShortcutGuide,
|
||||
|
||||
@@ -96,8 +96,6 @@ namespace CommonSharedConstants
|
||||
const wchar_t SHOW_ENVIRONMENT_VARIABLES_EVENT[] = L"Local\\PowerToysEnvironmentVariables-ShowEnvironmentVariablesEvent-1021f616-e951-4d64-b231-a8f972159978";
|
||||
const wchar_t SHOW_ENVIRONMENT_VARIABLES_ADMIN_EVENT[] = L"Local\\PowerToysEnvironmentVariables-EnvironmentVariablesAdminEvent-8c95d2ad-047c-49a2-9e8b-b4656326cfb2";
|
||||
|
||||
const wchar_t PROJECTS_EXIT_EVENT[] = L"Local\\PowerToys-Projects-ExitEvent-29a1566f-f4f8-4d56-9435-d2a437f727c6";
|
||||
|
||||
// Max DWORD for key code to disable keys.
|
||||
const DWORD VK_DISABLED = 0x100;
|
||||
}
|
||||
|
||||
@@ -69,10 +69,6 @@ struct LogSettings
|
||||
inline const static std::string environmentVariablesLoggerName = "environment-variables";
|
||||
inline const static std::wstring cmdNotFoundLogPath = L"Logs\\cmd-not-found-log.txt";
|
||||
inline const static std::string cmdNotFoundLoggerName = "cmd-not-found";
|
||||
inline const static std::string projectsLauncherLoggerName = "projects-launcher";
|
||||
inline const static std::wstring projectsLauncherLogPath = L"projects-launcher-log.txt";
|
||||
inline const static std::string projectsSnapshotToolLoggerName = "projects-snapshot-tool";
|
||||
inline const static std::wstring projectsSnapshotToolLogPath = L"projects-snapshot-tool-log.txt";
|
||||
inline const static int retention = 30;
|
||||
std::wstring logLevel;
|
||||
LogSettings();
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <future>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <atomic>
|
||||
|
||||
// OnThreadExecutor allows its caller to off-load some work to a persistently running background thread.
|
||||
// This might come in handy if you use the API which sets thread-wide global state and the state needs
|
||||
// to be isolated.
|
||||
|
||||
class OnThreadExecutor final
|
||||
{
|
||||
public:
|
||||
using task_t = std::packaged_task<void()>;
|
||||
|
||||
OnThreadExecutor() :
|
||||
_shutdown_request{ false },
|
||||
_worker_thread{ [this] { worker_thread(); } }
|
||||
{
|
||||
}
|
||||
|
||||
~OnThreadExecutor()
|
||||
{
|
||||
_shutdown_request = true;
|
||||
_task_cv.notify_one();
|
||||
_worker_thread.join();
|
||||
}
|
||||
|
||||
std::future<void> submit(task_t task)
|
||||
{
|
||||
auto future = task.get_future();
|
||||
std::lock_guard lock{ _task_mutex };
|
||||
_task_queue.emplace(std::move(task));
|
||||
_task_cv.notify_one();
|
||||
return future;
|
||||
}
|
||||
|
||||
void cancel()
|
||||
{
|
||||
std::lock_guard lock{ _task_mutex };
|
||||
_task_queue = {};
|
||||
_task_cv.notify_one();
|
||||
}
|
||||
|
||||
private:
|
||||
void worker_thread()
|
||||
{
|
||||
while (!_shutdown_request)
|
||||
{
|
||||
task_t task;
|
||||
{
|
||||
std::unique_lock task_lock{ _task_mutex };
|
||||
_task_cv.wait(task_lock, [this] { return !_task_queue.empty() || _shutdown_request; });
|
||||
if (_shutdown_request)
|
||||
{
|
||||
return;
|
||||
}
|
||||
task = std::move(_task_queue.front());
|
||||
_task_queue.pop();
|
||||
}
|
||||
task();
|
||||
}
|
||||
}
|
||||
|
||||
std::mutex _task_mutex;
|
||||
std::condition_variable _task_cv;
|
||||
std::atomic_bool _shutdown_request;
|
||||
std::queue<std::packaged_task<void()>> _task_queue;
|
||||
std::thread _worker_thread;
|
||||
};
|
||||
@@ -59,7 +59,6 @@ namespace powertoys_gpo {
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_ENVIRONMENT_VARIABLES = L"ConfigureEnabledUtilityEnvironmentVariables";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_QOI_PREVIEW = L"ConfigureEnabledUtilityFileExplorerQOIPreview";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_QOI_THUMBNAILS = L"ConfigureEnabledUtilityFileExplorerQOIThumbnails";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_PROJECTS = L"ConfigureEnabledUtilityProjects";
|
||||
|
||||
// The registry value names for PowerToys installer and update policies.
|
||||
const std::wstring POLICY_DISABLE_PER_USER_INSTALLATION = L"PerUserInstallationDisabled";
|
||||
@@ -367,11 +366,6 @@ namespace powertoys_gpo {
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_ADVANCED_PASTE);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredProjectsEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_PROJECTS);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredVideoConferenceMuteEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE);
|
||||
|
||||
@@ -27,18 +27,18 @@ enum class version_architecture
|
||||
version_architecture get_current_architecture();
|
||||
const wchar_t* get_architecture_string(const version_architecture);
|
||||
|
||||
inline std::wstring get_product_version()
|
||||
inline std::wstring get_product_version(bool includeV = true)
|
||||
{
|
||||
static std::wstring version = L"v" + std::to_wstring(VERSION_MAJOR) +
|
||||
static std::wstring version = (includeV ? L"v" : L"") + std::to_wstring(VERSION_MAJOR) +
|
||||
L"." + std::to_wstring(VERSION_MINOR) +
|
||||
L"." + std::to_wstring(VERSION_REVISION);
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
inline std::wstring get_std_product_version()
|
||||
inline std::wstring get_std_product_version(bool includeV = true)
|
||||
{
|
||||
static std::wstring version = L"v" + std::to_wstring(VERSION_MAJOR) +
|
||||
static std::wstring version = (includeV ? L"v" : L"") + std::to_wstring(VERSION_MAJOR) +
|
||||
L"." + std::to_wstring(VERSION_MINOR) +
|
||||
L"." + std::to_wstring(VERSION_REVISION) + L".0";
|
||||
|
||||
|
||||
@@ -57,8 +57,6 @@ properties:
|
||||
EnableQoiThumbnail: false
|
||||
PowerOcr:
|
||||
Enabled: false
|
||||
Projects:
|
||||
Enabled: false
|
||||
ShortcutGuide:
|
||||
Enabled: false
|
||||
VideoConference:
|
||||
|
||||
@@ -57,8 +57,6 @@ properties:
|
||||
EnableQoiThumbnail: true
|
||||
PowerOcr:
|
||||
Enabled: true
|
||||
Projects:
|
||||
Enabled: true
|
||||
ShortcutGuide:
|
||||
Enabled: true
|
||||
VideoConference:
|
||||
|
||||
@@ -356,16 +356,6 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityProjects" class="Both" displayName="$(string.ConfigureEnabledUtilityProjects)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityProjects">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_81_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityQuickAccent" class="Both" displayName="$(string.ConfigureEnabledUtilityQuickAccent)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityQuickAccent">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
<string id="InstallerUpdates">Installer and Updates</string>
|
||||
<string id="PowerToysRun">PowerToys Run</string>
|
||||
<string id="AdvancedPaste">Advanced Paste</string>
|
||||
<string id="Projects">Projects</string>
|
||||
|
||||
<string id="SUPPORTED_POWERTOYS_0_64_0">PowerToys version 0.64.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_68_0">PowerToys version 0.68.0 or later</string>
|
||||
@@ -108,12 +107,6 @@ If you don't configure this setting, users are able to enable or disable the plu
|
||||
You can override this policy for individual plugins using the policy "Configure enabled state for individual plugins".
|
||||
|
||||
Note: Changes require a restart of PowerToys Run.
|
||||
</string>
|
||||
<string id="ConfigureEnabledUtilityProjects">This policy configures the enabled disable state for the Projects utility.
|
||||
|
||||
If you enable or don't configure this policy, the user takes control over the enabled state of the Projects utility.
|
||||
|
||||
If you disable this policy, the user won't be able to enable Enable and use the Projects utility.
|
||||
</string>
|
||||
<string id="PowerToysRunIndividualPluginEnabledStateDescription">With this policy you can configure an individual enabled state for each PowerToys Run plugin that you add to the list.
|
||||
|
||||
@@ -164,7 +157,6 @@ If you disable this policy, the user won't be able to enable Enable paste with A
|
||||
<string id="ConfigureEnabledUtilityPeek">Peek: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityPowerRename">Power Rename: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityPowerLauncher">PowerToys Run: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityProjects">PowerToys Projects: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityQuickAccent">Quick Accent: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityRegistryPreview">Registry Preview: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityScreenRuler">Screen Ruler: Configure enabled state</string>
|
||||
|
||||
@@ -3,15 +3,14 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.Settings;
|
||||
using AdvancedPaste.ViewModels;
|
||||
using ManagedCommon;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Windows.Graphics;
|
||||
using WinUIEx;
|
||||
using static AdvancedPaste.Helpers.NativeMethods;
|
||||
@@ -47,6 +46,7 @@ namespace AdvancedPaste
|
||||
Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder().UseContentRoot(AppContext.BaseDirectory).ConfigureServices((context, services) =>
|
||||
{
|
||||
services.AddSingleton<OptionsViewModel>();
|
||||
services.AddSingleton<IUserSettings, UserSettings>();
|
||||
}).Build();
|
||||
|
||||
viewModel = GetService<OptionsViewModel>();
|
||||
|
||||
@@ -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 System;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using AdvancedPaste.Helpers;
|
||||
@@ -20,14 +19,13 @@ namespace AdvancedPaste.Controls
|
||||
public sealed partial class PromptBox : Microsoft.UI.Xaml.Controls.UserControl
|
||||
{
|
||||
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
private UserSettings _userSettings;
|
||||
private readonly IUserSettings _userSettings;
|
||||
|
||||
public static readonly DependencyProperty PromptProperty = DependencyProperty.Register(
|
||||
nameof(Prompt),
|
||||
typeof(string),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: string.Empty));
|
||||
nameof(Prompt),
|
||||
typeof(string),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: string.Empty));
|
||||
|
||||
public OptionsViewModel ViewModel { get; private set; }
|
||||
|
||||
@@ -38,10 +36,10 @@ namespace AdvancedPaste.Controls
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PlaceholderTextProperty = DependencyProperty.Register(
|
||||
nameof(PlaceholderText),
|
||||
typeof(string),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: string.Empty));
|
||||
nameof(PlaceholderText),
|
||||
typeof(string),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: string.Empty));
|
||||
|
||||
public string PlaceholderText
|
||||
{
|
||||
@@ -50,10 +48,10 @@ namespace AdvancedPaste.Controls
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register(
|
||||
nameof(Footer),
|
||||
typeof(object),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
nameof(Footer),
|
||||
typeof(object),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
public object Footer
|
||||
{
|
||||
@@ -65,7 +63,7 @@ namespace AdvancedPaste.Controls
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
_userSettings = new UserSettings();
|
||||
_userSettings = App.GetService<IUserSettings>();
|
||||
|
||||
ViewModel = App.GetService<OptionsViewModel>();
|
||||
}
|
||||
@@ -80,8 +78,6 @@ namespace AdvancedPaste.Controls
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteGenerateCustomFormatEvent());
|
||||
|
||||
VisualStateManager.GoToState(this, "LoadingState", true);
|
||||
string inputInstructions = InputTxtBox.Text;
|
||||
ViewModel.SaveQuery(inputInstructions);
|
||||
|
||||
@@ -3,21 +3,20 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.Settings;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Windows.Graphics;
|
||||
using WinUIEx;
|
||||
using WinUIEx.Messaging;
|
||||
using static AdvancedPaste.Helpers.NativeMethods;
|
||||
|
||||
namespace AdvancedPaste
|
||||
{
|
||||
public sealed partial class MainWindow : WindowEx, IDisposable
|
||||
{
|
||||
private WindowMessageMonitor _msgMonitor;
|
||||
private readonly WindowMessageMonitor _msgMonitor;
|
||||
private readonly IUserSettings _userSettings;
|
||||
|
||||
private bool _disposedValue;
|
||||
|
||||
@@ -25,6 +24,8 @@ namespace AdvancedPaste
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
_userSettings = App.GetService<IUserSettings>();
|
||||
|
||||
AppWindow.SetIcon("Assets/AdvancedPaste/AdvancedPaste.ico");
|
||||
this.ExtendsContentIntoTitleBar = true;
|
||||
this.SetTitleBar(titleBar);
|
||||
@@ -32,6 +33,8 @@ namespace AdvancedPaste
|
||||
var loader = ResourceLoaderInstance.ResourceLoader;
|
||||
Title = loader.GetString("WindowTitle");
|
||||
|
||||
Activated += OnActivated;
|
||||
|
||||
_msgMonitor = new WindowMessageMonitor(this);
|
||||
_msgMonitor.WindowMessageReceived += (_, e) =>
|
||||
{
|
||||
@@ -47,6 +50,14 @@ namespace AdvancedPaste
|
||||
WindowHelpers.BringToForeground(this.GetWindowHandle());
|
||||
}
|
||||
|
||||
private void OnActivated(object sender, WindowActivatedEventArgs args)
|
||||
{
|
||||
if (_userSettings.CloseAfterLosingFocus && args.WindowActivationState == WindowActivationState.Deactivated)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposedValue)
|
||||
@@ -66,11 +77,15 @@ namespace AdvancedPaste
|
||||
|
||||
private void WindowEx_Closed(object sender, Microsoft.UI.Xaml.WindowEventArgs args)
|
||||
{
|
||||
Windows.Win32.PInvoke.ShowWindow((Windows.Win32.Foundation.HWND)this.GetWindowHandle(), Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD.SW_HIDE);
|
||||
|
||||
Hide();
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void Hide()
|
||||
{
|
||||
Windows.Win32.PInvoke.ShowWindow(new Windows.Win32.Foundation.HWND(this.GetWindowHandle()), Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD.SW_HIDE);
|
||||
}
|
||||
|
||||
public void SetFocus()
|
||||
{
|
||||
MainPage.CustomFormatTextBox.InputTxtBox.Focus(FocusState.Programmatic);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AdvancedPaste.Helpers;
|
||||
@@ -86,6 +87,11 @@ namespace AdvancedPaste.Pages
|
||||
|
||||
_dispatcherQueue.TryEnqueue(async () =>
|
||||
{
|
||||
// Clear to avoid leaks due to Garbage Collection not clearing the bitmap from memory. Fix for https://github.com/microsoft/PowerToys/issues/33423
|
||||
clipboardHistory.Where(x => x.Image is not null)
|
||||
.ToList()
|
||||
.ForEach(x => x.Image.ClearValue(BitmapImage.UriSourceProperty));
|
||||
|
||||
clipboardHistory.Clear();
|
||||
|
||||
foreach (var item in items)
|
||||
@@ -225,6 +231,7 @@ namespace AdvancedPaste.Pages
|
||||
var item = e.ClickedItem as ClipboardItem;
|
||||
if (item is not null)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteClipboardItemClicked());
|
||||
if (!string.IsNullOrEmpty(item.Content))
|
||||
{
|
||||
ClipboardHelper.SetClipboardTextContent(item.Content);
|
||||
|
||||
@@ -33,6 +33,8 @@ namespace AdvancedPaste.Helpers
|
||||
|
||||
private string _openAIKey;
|
||||
|
||||
private string _modelName = "gpt-3.5-turbo-instruct";
|
||||
|
||||
public bool IsAIEnabled => !string.IsNullOrEmpty(this._openAIKey);
|
||||
|
||||
public AICompletionsHelper()
|
||||
@@ -69,14 +71,14 @@ namespace AdvancedPaste.Helpers
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public string GetAICompletion(string systemInstructions, string userMessage)
|
||||
private Response<Completions> GetAICompletion(string systemInstructions, string userMessage)
|
||||
{
|
||||
OpenAIClient azureAIClient = new OpenAIClient(_openAIKey);
|
||||
|
||||
var response = azureAIClient.GetCompletions(
|
||||
new CompletionsOptions()
|
||||
{
|
||||
DeploymentName = "gpt-3.5-turbo-instruct",
|
||||
DeploymentName = _modelName,
|
||||
Prompts =
|
||||
{
|
||||
systemInstructions + "\n\n" + userMessage,
|
||||
@@ -90,7 +92,7 @@ namespace AdvancedPaste.Helpers
|
||||
Console.WriteLine("Cut off due to length constraints");
|
||||
}
|
||||
|
||||
return response.Value.Choices[0].Text;
|
||||
return response;
|
||||
}
|
||||
|
||||
public AICompletionsResponse AIFormatString(string inputInstructions, string inputString)
|
||||
@@ -109,10 +111,16 @@ Output:
|
||||
";
|
||||
|
||||
string aiResponse = null;
|
||||
Response<Completions> rawAIResponse = null;
|
||||
int apiRequestStatus = (int)HttpStatusCode.OK;
|
||||
try
|
||||
{
|
||||
aiResponse = this.GetAICompletion(systemInstructions, userMessage);
|
||||
rawAIResponse = this.GetAICompletion(systemInstructions, userMessage);
|
||||
aiResponse = rawAIResponse.Value.Choices[0].Text;
|
||||
|
||||
int promptTokens = rawAIResponse.Value.Usage.PromptTokens;
|
||||
int completionTokens = rawAIResponse.Value.Usage.CompletionTokens;
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteGenerateCustomFormatEvent(promptTokens, completionTokens, _modelName));
|
||||
}
|
||||
catch (Azure.RequestFailedException error)
|
||||
{
|
||||
|
||||
@@ -9,5 +9,7 @@ namespace AdvancedPaste.Settings
|
||||
public bool ShowCustomPreview { get; }
|
||||
|
||||
public bool SendPasteKeyCombination { get; }
|
||||
|
||||
public bool CloseAfterLosingFocus { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@ namespace AdvancedPaste.Helpers
|
||||
{
|
||||
internal static class JsonHelper
|
||||
{
|
||||
// Ini parts regex
|
||||
private static readonly Regex IniSectionNameRegex = new Regex(@"^\[(.+)\]");
|
||||
private static readonly Regex IniValueLineRegex = new Regex(@"(.+?)\s*=\s*(.*)");
|
||||
|
||||
// List of supported CSV delimiters and Regex to detect separator property
|
||||
private static readonly char[] CsvDelimArry = [',', ';', '\t'];
|
||||
private static readonly Regex CsvSepIdentifierRegex = new Regex(@"^sep=(.)$", RegexOptions.IgnoreCase);
|
||||
@@ -45,6 +49,7 @@ namespace AdvancedPaste.Helpers
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(text);
|
||||
Logger.LogDebug("Converted from XML.");
|
||||
jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -52,6 +57,75 @@ namespace AdvancedPaste.Helpers
|
||||
Logger.LogError("Failed parsing input as xml", ex);
|
||||
}
|
||||
|
||||
// Try convert Ini
|
||||
// (Must come before CSV that ini is not false detected as CSV.)
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(jsonText))
|
||||
{
|
||||
var ini = new Dictionary<string, Dictionary<string, string>>();
|
||||
var lastSectionName = string.Empty;
|
||||
|
||||
string[] lines = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
// Skipp comment lines.
|
||||
// (Comments are lines that starts with a semicolon.
|
||||
// This also skips commented key-value-pairs.)
|
||||
lines = lines.Where(l => !l.StartsWith(';')).ToArray();
|
||||
|
||||
// Validate content as ini
|
||||
// (First line is a section name and second line is a section name or a key-value-pair.
|
||||
// For the second line we check both, in case the first ini section is empty.)
|
||||
if (lines.Length >= 2 && IniSectionNameRegex.IsMatch(lines[0]) &&
|
||||
(IniSectionNameRegex.IsMatch(lines[1]) || IniValueLineRegex.IsMatch(lines[1])))
|
||||
{
|
||||
// Parse and convert Ini
|
||||
foreach (string line in lines)
|
||||
{
|
||||
Match lineSectionNameCheck = IniSectionNameRegex.Match(line);
|
||||
Match lineKeyValuePairCheck = IniValueLineRegex.Match(line);
|
||||
|
||||
if (lineSectionNameCheck.Success)
|
||||
{
|
||||
// Section name (Group 1)
|
||||
lastSectionName = lineSectionNameCheck.Groups[1].Value.Trim();
|
||||
if (string.IsNullOrWhiteSpace(lastSectionName))
|
||||
{
|
||||
throw new FormatException("Invalid ini file format: Empty section name.");
|
||||
}
|
||||
|
||||
ini.Add(lastSectionName, new Dictionary<string, string>());
|
||||
}
|
||||
else if (!lineKeyValuePairCheck.Success)
|
||||
{
|
||||
// Fail if it is not a key-value-pair (and was not detected as section name before).
|
||||
throw new FormatException("Invalid ini file format: Invalid line.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Key-value-pair (Group 1=Key; Group 2=Value)
|
||||
string iniKeyName = lineKeyValuePairCheck.Groups[1].Value.Trim();
|
||||
if (string.IsNullOrWhiteSpace(iniKeyName))
|
||||
{
|
||||
throw new FormatException("Invalid ini file format: Empty value name (key).");
|
||||
}
|
||||
|
||||
string iniValueData = lineKeyValuePairCheck.Groups[2].Value;
|
||||
ini[lastSectionName].Add(iniKeyName, iniValueData);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to JSON
|
||||
Logger.LogDebug("Converted from Ini.");
|
||||
jsonText = JsonConvert.SerializeObject(ini, Newtonsoft.Json.Formatting.Indented);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed parsing input as ini", ex);
|
||||
}
|
||||
|
||||
// Try convert CSV
|
||||
try
|
||||
{
|
||||
|
||||
@@ -24,12 +24,15 @@ namespace AdvancedPaste.Settings
|
||||
|
||||
public bool SendPasteKeyCombination { get; private set; }
|
||||
|
||||
public bool CloseAfterLosingFocus { get; private set; }
|
||||
|
||||
public UserSettings()
|
||||
{
|
||||
_settingsUtils = new SettingsUtils();
|
||||
|
||||
ShowCustomPreview = true;
|
||||
SendPasteKeyCombination = true;
|
||||
CloseAfterLosingFocus = false;
|
||||
|
||||
LoadSettingsFromJson();
|
||||
|
||||
@@ -61,6 +64,7 @@ namespace AdvancedPaste.Settings
|
||||
{
|
||||
ShowCustomPreview = settings.Properties.ShowCustomPreview;
|
||||
SendPasteKeyCombination = settings.Properties.SendPasteKeyCombination;
|
||||
CloseAfterLosingFocus = settings.Properties.CloseAfterLosingFocus;
|
||||
}
|
||||
|
||||
retry = false;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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.
|
||||
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace AdvancedPaste.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class AdvancedPasteClipboardItemClicked : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,19 @@ namespace AdvancedPaste.Telemetry
|
||||
[EventData]
|
||||
public class AdvancedPasteGenerateCustomFormatEvent : EventBase, IEvent
|
||||
{
|
||||
public int PromptTokens { get; set; }
|
||||
|
||||
public int CompletionTokens { get; set; }
|
||||
|
||||
public string ModelName { get; set; }
|
||||
|
||||
public AdvancedPasteGenerateCustomFormatEvent(int promptTokens, int completionTokens, string modelName)
|
||||
{
|
||||
this.PromptTokens = promptTokens;
|
||||
this.CompletionTokens = completionTokens;
|
||||
ModelName = modelName;
|
||||
}
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,12 @@ namespace AdvancedPaste.ViewModels
|
||||
public partial class OptionsViewModel : ObservableObject
|
||||
{
|
||||
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
private readonly IUserSettings _userSettings;
|
||||
|
||||
private App app = App.Current as App;
|
||||
|
||||
private AICompletionsHelper aiHelper;
|
||||
|
||||
private UserSettings _userSettings;
|
||||
|
||||
public DataPackageView ClipboardData { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
@@ -50,10 +49,10 @@ namespace AdvancedPaste.ViewModels
|
||||
[NotifyPropertyChangedFor(nameof(InputTxtBoxErrorText))]
|
||||
private int _apiRequestStatus;
|
||||
|
||||
public OptionsViewModel()
|
||||
public OptionsViewModel(IUserSettings userSettings)
|
||||
{
|
||||
aiHelper = new AICompletionsHelper();
|
||||
_userSettings = new UserSettings();
|
||||
_userSettings = userSettings;
|
||||
|
||||
IsCustomAIEnabled = IsClipboardDataText && aiHelper.IsAIEnabled;
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.0 KiB |
@@ -1,146 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34622.214
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProjectsSnapshotTool", "ProjectsSnapshotTool\ProjectsSnapshotTool.vcxproj", "{3D63307B-9D27-44FD-B033-B26F39245B85}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "projects-common", "projects-common", "{BA45247D-3046-408D-BE01-128587A7799F}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
projects-common\AppUtils.h = projects-common\AppUtils.h
|
||||
projects-common\Data.h = projects-common\Data.h
|
||||
projects-common\GuidUtils.h = projects-common\GuidUtils.h
|
||||
projects-common\json.h = projects-common\json.h
|
||||
projects-common\MonitorEnumerator.h = projects-common\MonitorEnumerator.h
|
||||
projects-common\VirtualDesktop.h = projects-common\VirtualDesktop.h
|
||||
projects-common\WindowEnumerator.h = projects-common\WindowEnumerator.h
|
||||
projects-common\WindowFilter.h = projects-common\WindowFilter.h
|
||||
projects-common\WindowUtils.h = projects-common\WindowUtils.h
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProjectsLauncher", "ProjectsLauncher\ProjectsLauncher.vcxproj", "{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjectsEditor", "ProjectsEditor\ProjectsEditor.csproj", "{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedCommon", "..\..\common\ManagedCommon\ManagedCommon.csproj", "{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.Interop", "..\..\common\interop\PowerToys.Interop.vcxproj", "{F055103B-F80B-4D0C-BF48-057C55620033}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedTelemetry", "..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj", "{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|x64.Build.0 = Debug|x64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|x86.Build.0 = Debug|Win32
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Release|Any CPU.Build.0 = Release|x64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Release|x64.ActiveCfg = Release|x64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Release|x64.Build.0 = Release|x64
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Release|x86.ActiveCfg = Release|Win32
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85}.Release|x86.Build.0 = Release|Win32
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|x64.Build.0 = Debug|x64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|x86.Build.0 = Debug|Win32
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|Any CPU.Build.0 = Release|x64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|x64.ActiveCfg = Release|x64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|x64.Build.0 = Release|x64
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|x86.ActiveCfg = Release|Win32
|
||||
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|x86.Build.0 = Release|Win32
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x64.Build.0 = Debug|x64
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x64.ActiveCfg = Release|x64
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x64.Build.0 = Release|x64
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Debug|x64.Build.0 = Debug|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Debug|x86.Build.0 = Debug|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Release|Any CPU.Build.0 = Release|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Release|x64.ActiveCfg = Release|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Release|x64.Build.0 = Release|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Release|x86.ActiveCfg = Release|x64
|
||||
{A881F6EB-6EDA-4674-A6B7-598F0A8E7048}.Release|x86.Build.0 = Release|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x64.Build.0 = Debug|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x86.Build.0 = Debug|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|Any CPU.Build.0 = Release|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.ActiveCfg = Release|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.Build.0 = Release|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x86.ActiveCfg = Release|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x86.Build.0 = Release|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Debug|x64.Build.0 = Debug|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Debug|x86.Build.0 = Debug|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Release|Any CPU.Build.0 = Release|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Release|x64.ActiveCfg = Release|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Release|x64.Build.0 = Release|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Release|x86.ActiveCfg = Release|x64
|
||||
{6CE421AD-D249-4BD1-9ADA-B46DA18AADEE}.Release|x86.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BE6AD818-2650-419C-8FDE-535C22ED09B3}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
|
||||
</startup>
|
||||
<runtime>
|
||||
<AppContextSwitchOverrides value = "Switch.System.Windows.DoNotScaleForDpiChanges=false"/>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -1,20 +0,0 @@
|
||||
<Application
|
||||
x:Class="ProjectsEditor.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ProjectsEditor"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
Exit="OnExit"
|
||||
Startup="OnStartup">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ui:ThemeResources />
|
||||
<ui:XamlControlsResources />
|
||||
<ResourceDictionary Source="pack://application:,,,/Styles/ButtonStyles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style x:Key="HeadingTextBlock" TargetType="TextBlock" />
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -1,109 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using ManagedCommon;
|
||||
using ProjectsEditor.Common;
|
||||
using ProjectsEditor.Utils;
|
||||
using ProjectsEditor.ViewModels;
|
||||
|
||||
namespace ProjectsEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application, IDisposable
|
||||
{
|
||||
public static ProjectsEditorIO ProjectsEditorIO { get; private set; }
|
||||
|
||||
private MainWindow _mainWindow;
|
||||
|
||||
private MainViewModel _mainViewModel;
|
||||
|
||||
private ThemeManager _themeManager;
|
||||
|
||||
private bool _isDisposed;
|
||||
|
||||
public App()
|
||||
{
|
||||
ProjectsEditorIO = new ProjectsEditorIO();
|
||||
}
|
||||
|
||||
private void OnStartup(object sender, StartupEventArgs e)
|
||||
{
|
||||
if (PowerToys.GPOWrapperProjection.GPOWrapper.GetConfiguredProjectsEnabledValue() == PowerToys.GPOWrapperProjection.GpoRuleConfigured.Disabled)
|
||||
{
|
||||
Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
|
||||
Shutdown(0);
|
||||
return;
|
||||
}
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||
|
||||
Logger.InitializeLogger("\\Projects\\Logs");
|
||||
|
||||
_themeManager = new ThemeManager(this);
|
||||
|
||||
if (_mainViewModel == null)
|
||||
{
|
||||
_mainViewModel = new MainViewModel(ProjectsEditorIO);
|
||||
}
|
||||
|
||||
var parseResult = ProjectsEditorIO.ParseProjects(_mainViewModel);
|
||||
|
||||
string[] args = Environment.GetCommandLineArgs();
|
||||
if (args != null && args.Length > 1)
|
||||
{
|
||||
Logger.LogInfo($"Started with a parameter: {args[1]}. Trying to launch that project.");
|
||||
_mainViewModel.LaunchProject(args[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
// normal start of editor
|
||||
if (_mainWindow == null)
|
||||
{
|
||||
_mainWindow = new MainWindow(_mainViewModel);
|
||||
}
|
||||
|
||||
// reset main window owner to keep it on the top
|
||||
_mainWindow.ShowActivated = true;
|
||||
_mainWindow.Topmost = true;
|
||||
_mainWindow.Show();
|
||||
|
||||
// we can reset topmost flag after it's opened
|
||||
_mainWindow.Topmost = false;
|
||||
}
|
||||
|
||||
private void OnExit(object sender, ExitEventArgs e)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs args)
|
||||
{
|
||||
// TODO: log the error and show an error message
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_themeManager?.Dispose();
|
||||
}
|
||||
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using ControlzEx.Theming;
|
||||
|
||||
namespace ProjectsEditor.Common
|
||||
{
|
||||
public class CustomLibraryThemeProvider : LibraryThemeProvider
|
||||
{
|
||||
public static readonly CustomLibraryThemeProvider DefaultInstance = new CustomLibraryThemeProvider();
|
||||
|
||||
public CustomLibraryThemeProvider()
|
||||
: base(true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void FillColorSchemeValues(Dictionary<string, string> values, RuntimeThemeColorValues colorValues)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// 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.
|
||||
|
||||
namespace ProjectsEditor.Common
|
||||
{
|
||||
public enum Theme
|
||||
{
|
||||
System,
|
||||
Light,
|
||||
Dark,
|
||||
HighContrastOne,
|
||||
HighContrastTwo,
|
||||
HighContrastBlack,
|
||||
HighContrastWhite,
|
||||
}
|
||||
|
||||
public enum AppTheme
|
||||
{
|
||||
Dark = 0,
|
||||
Light = 1,
|
||||
}
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// using ManagedCommon;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace ProjectsEditor.Common
|
||||
{
|
||||
public class ThemeManager : IDisposable
|
||||
{
|
||||
private readonly Application _app;
|
||||
private const string LightTheme = "Light.Accent1";
|
||||
private const string DarkTheme = "Dark.Accent1";
|
||||
private const string HighContrastOneTheme = "HighContrast.Accent2";
|
||||
private const string HighContrastTwoTheme = "HighContrast.Accent3";
|
||||
private const string HighContrastBlackTheme = "HighContrast.Accent4";
|
||||
private const string HighContrastWhiteTheme = "HighContrast.Accent5";
|
||||
|
||||
private static Theme _currentTheme;
|
||||
private Theme _settingsTheme;
|
||||
private bool _disposed;
|
||||
|
||||
public event ThemeChangedHandler ThemeChanged;
|
||||
|
||||
public ThemeManager(Application app)
|
||||
{
|
||||
_app = app;
|
||||
|
||||
Uri highContrastOneThemeUri = new Uri("pack://application:,,,/Themes/HighContrast1.xaml");
|
||||
Uri highContrastTwoThemeUri = new Uri("pack://application:,,,/Themes/HighContrast2.xaml");
|
||||
Uri highContrastBlackThemeUri = new Uri("pack://application:,,,/Themes/HighContrastWhite.xaml");
|
||||
Uri highContrastWhiteThemeUri = new Uri("pack://application:,,,/Themes/HighContrastBlack.xaml");
|
||||
Uri lightThemeUri = new Uri("pack://application:,,,/Themes/Light.xaml");
|
||||
Uri darkThemeUri = new Uri("pack://application:,,,/Themes/Dark.xaml");
|
||||
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new ControlzEx.Theming.LibraryTheme(
|
||||
highContrastOneThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new ControlzEx.Theming.LibraryTheme(
|
||||
highContrastTwoThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new ControlzEx.Theming.LibraryTheme(
|
||||
highContrastBlackThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new ControlzEx.Theming.LibraryTheme(
|
||||
highContrastWhiteThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new ControlzEx.Theming.LibraryTheme(
|
||||
lightThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
|
||||
new ControlzEx.Theming.LibraryTheme(
|
||||
darkThemeUri,
|
||||
CustomLibraryThemeProvider.DefaultInstance));
|
||||
|
||||
ResetTheme();
|
||||
ControlzEx.Theming.ThemeManager.Current.ThemeSyncMode = ControlzEx.Theming.ThemeSyncMode.SyncWithAppMode;
|
||||
ControlzEx.Theming.ThemeManager.Current.ThemeChanged += Current_ThemeChanged;
|
||||
SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged;
|
||||
}
|
||||
|
||||
private void SystemParameters_StaticPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(SystemParameters.HighContrast))
|
||||
{
|
||||
ResetTheme();
|
||||
}
|
||||
}
|
||||
|
||||
public static Theme GetCurrentTheme()
|
||||
{
|
||||
return _currentTheme;
|
||||
}
|
||||
|
||||
private static Theme GetHighContrastBaseType()
|
||||
{
|
||||
string registryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes";
|
||||
string theme = (string)Registry.GetValue(registryKey, "CurrentTheme", string.Empty);
|
||||
theme = theme.Split('\\').Last().Split('.').First().ToString();
|
||||
|
||||
switch (theme)
|
||||
{
|
||||
case "hc1":
|
||||
return Theme.HighContrastOne;
|
||||
case "hc2":
|
||||
return Theme.HighContrastTwo;
|
||||
case "hcwhite":
|
||||
return Theme.HighContrastWhite;
|
||||
case "hcblack":
|
||||
return Theme.HighContrastBlack;
|
||||
default:
|
||||
return Theme.HighContrastOne;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetTheme()
|
||||
{
|
||||
ChangeTheme(_settingsTheme == Theme.System ? Theme.System : _currentTheme);
|
||||
}
|
||||
|
||||
public static string GetWindowsBaseColor()
|
||||
{
|
||||
return ControlzEx.Theming.WindowsThemeHelper.GetWindowsBaseColor();
|
||||
}
|
||||
|
||||
public void ChangeTheme(Theme theme, bool fromSettings = false)
|
||||
{
|
||||
if (fromSettings)
|
||||
{
|
||||
_settingsTheme = theme;
|
||||
}
|
||||
|
||||
Theme oldTheme = _currentTheme;
|
||||
|
||||
if (theme == Theme.System)
|
||||
{
|
||||
_currentTheme = Theme.System;
|
||||
if (ControlzEx.Theming.WindowsThemeHelper.IsHighContrastEnabled())
|
||||
{
|
||||
Theme highContrastBaseType = GetHighContrastBaseType();
|
||||
ChangeTheme(highContrastBaseType, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
string baseColor = ControlzEx.Theming.WindowsThemeHelper.GetWindowsBaseColor();
|
||||
ChangeTheme((Theme)Enum.Parse(typeof(Theme), baseColor));
|
||||
}
|
||||
}
|
||||
else if (theme == Theme.HighContrastOne)
|
||||
{
|
||||
_currentTheme = Theme.HighContrastOne;
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastOneTheme);
|
||||
}
|
||||
else if (theme == Theme.HighContrastTwo)
|
||||
{
|
||||
_currentTheme = Theme.HighContrastTwo;
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastTwoTheme);
|
||||
}
|
||||
else if (theme == Theme.HighContrastWhite)
|
||||
{
|
||||
_currentTheme = Theme.HighContrastWhite;
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastWhiteTheme);
|
||||
}
|
||||
else if (theme == Theme.HighContrastBlack)
|
||||
{
|
||||
_currentTheme = Theme.HighContrastBlack;
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastBlackTheme);
|
||||
}
|
||||
else if (theme == Theme.Light)
|
||||
{
|
||||
_currentTheme = Theme.Light;
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, LightTheme);
|
||||
}
|
||||
else if (theme == Theme.Dark)
|
||||
{
|
||||
_currentTheme = Theme.Dark;
|
||||
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, DarkTheme);
|
||||
}
|
||||
|
||||
ThemeChanged?.Invoke(oldTheme, _currentTheme);
|
||||
}
|
||||
|
||||
private void Current_ThemeChanged(object sender, ControlzEx.Theming.ThemeChangedEventArgs e)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ThemeChanged -= Current_ThemeChanged;
|
||||
try
|
||||
{
|
||||
ResetTheme();
|
||||
}
|
||||
finally
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ThemeChanged += Current_ThemeChanged;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
ControlzEx.Theming.ThemeManager.Current.ThemeChanged -= Current_ThemeChanged;
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void ThemeChangedHandler(Theme oldTheme, Theme newTheme);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ProjectsEditor.Converters
|
||||
{
|
||||
public class BooleanToInvertedVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if ((bool)value)
|
||||
{
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
return Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Projects.Data;
|
||||
using ProjectsEditor.Utils;
|
||||
using static ProjectsEditor.Data.ProjectsData;
|
||||
|
||||
namespace ProjectsEditor.Data
|
||||
{
|
||||
public class ProjectsData : ProjectsEditorData<ProjectsListWrapper>
|
||||
{
|
||||
public string File
|
||||
{
|
||||
get
|
||||
{
|
||||
return FolderUtils.DataFolder() + "\\projects.json";
|
||||
}
|
||||
}
|
||||
|
||||
public struct ApplicationWrapper
|
||||
{
|
||||
public struct WindowPositionWrapper
|
||||
{
|
||||
public int X { get; set; }
|
||||
|
||||
public int Y { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
}
|
||||
|
||||
public string Application { get; set; }
|
||||
|
||||
public string ApplicationPath { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public string PackageFullName { get; set; }
|
||||
|
||||
public string CommandLineArguments { get; set; }
|
||||
|
||||
public bool Minimized { get; set; }
|
||||
|
||||
public bool Maximized { get; set; }
|
||||
|
||||
public WindowPositionWrapper Position { get; set; }
|
||||
|
||||
public int Monitor { get; set; }
|
||||
}
|
||||
|
||||
public struct MonitorConfigurationWrapper
|
||||
{
|
||||
public struct MonitorRectWrapper
|
||||
{
|
||||
public int Top { get; set; }
|
||||
|
||||
public int Left { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
public string InstanceId { get; set; }
|
||||
|
||||
public int MonitorNumber { get; set; }
|
||||
|
||||
public int Dpi { get; set; }
|
||||
|
||||
public MonitorRectWrapper MonitorRectDpiAware { get; set; }
|
||||
|
||||
public MonitorRectWrapper MonitorRectDpiUnaware { get; set; }
|
||||
}
|
||||
|
||||
public struct ProjectWrapper
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public long CreationTime { get; set; }
|
||||
|
||||
public long LastLaunchedTime { get; set; }
|
||||
|
||||
public bool IsShortcutNeeded { get; set; }
|
||||
|
||||
public List<MonitorConfigurationWrapper> MonitorConfiguration { get; set; }
|
||||
|
||||
public List<ApplicationWrapper> Applications { get; set; }
|
||||
}
|
||||
|
||||
public struct ProjectsListWrapper
|
||||
{
|
||||
public List<ProjectWrapper> Projects { get; set; }
|
||||
}
|
||||
|
||||
public enum OrderBy
|
||||
{
|
||||
LastViewed = 0,
|
||||
Created = 1,
|
||||
Name = 2,
|
||||
Unknown = 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.Text.Json;
|
||||
using ProjectsEditor.Utils;
|
||||
|
||||
namespace Projects.Data
|
||||
{
|
||||
public class ProjectsEditorData<T>
|
||||
{
|
||||
protected JsonSerializerOptions JsonOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
return new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = new DashCaseNamingPolicy(),
|
||||
WriteIndented = true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public T Read(string file)
|
||||
{
|
||||
IOUtils ioUtils = new IOUtils();
|
||||
string data = ioUtils.ReadFile(file);
|
||||
return JsonSerializer.Deserialize<T>(data, JsonOptions);
|
||||
}
|
||||
|
||||
public string Serialize(T data)
|
||||
{
|
||||
return JsonSerializer.Serialize(data, JsonOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Automation.Peers;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace ProjectsEditor
|
||||
{
|
||||
public class HeadingTextBlock : TextBlock
|
||||
{
|
||||
protected override AutomationPeer OnCreateAutomationPeer()
|
||||
{
|
||||
return new HeadingTextBlockAutomationPeer(this);
|
||||
}
|
||||
|
||||
internal sealed class HeadingTextBlockAutomationPeer : TextBlockAutomationPeer
|
||||
{
|
||||
public HeadingTextBlockAutomationPeer(HeadingTextBlock owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
protected override AutomationControlType GetAutomationControlTypeCore()
|
||||
{
|
||||
return AutomationControlType.Header;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,322 +0,0 @@
|
||||
<Page
|
||||
x:Class="ProjectsEditor.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:props="clr-namespace:ProjectsEditor.Properties"
|
||||
xmlns:converters="clr-namespace:ProjectsEditor.Converters"
|
||||
xmlns:local="clr-namespace:ProjectsEditor"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
Title="MainPage">
|
||||
<Page.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis" />
|
||||
<converters:BooleanToInvertedVisibilityConverter x:Key="BooleanToInvertedVisibilityConverter" />
|
||||
<Thickness x:Key="ContentDialogPadding">24,16,0,24</Thickness>
|
||||
<Thickness x:Key="ContentDialogCommandSpaceMargin">0,24,24,0</Thickness>
|
||||
<Style x:Key="DeleteButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="{DynamicResource TertiaryBackgroundBrush}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="Transparent" Padding="26,6,26,6">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource TitleBarSecondaryForegroundBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource TitleBarSecondaryForegroundBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Page.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<local:HeadingTextBlock
|
||||
x:Name="ProjectsHeaderBlock"
|
||||
AutomationProperties.HeadingLevel="Level1"
|
||||
FontSize="24"
|
||||
FontWeight="SemiBold"
|
||||
Text="{x:Static props:Resources.Projects}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Grid.Row="0"
|
||||
Margin="40,20,40,20"/>
|
||||
|
||||
<Button
|
||||
x:Name="NewProjectButton"
|
||||
Height="36"
|
||||
Padding="0"
|
||||
Grid.Row="0"
|
||||
Margin="0,20,40,20"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
AutomationProperties.Name="{x:Static props:Resources.CreateProject}"
|
||||
Click="NewProjectButton_Click"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
TabIndex="3">
|
||||
<StackPanel Margin="12, 8, 12, 8" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
AutomationProperties.Name="{x:Static props:Resources.CreateProject}"
|
||||
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||
Foreground="{DynamicResource AccentButtonForeground}"
|
||||
Text="" />
|
||||
<TextBlock
|
||||
Margin="12,-3,0,0"
|
||||
Foreground="{DynamicResource AccentButtonForeground}"
|
||||
Text="{x:Static props:Resources.CreateProject}" />
|
||||
</StackPanel>
|
||||
<Button.Effect>
|
||||
<DropShadowEffect
|
||||
BlurRadius="6"
|
||||
Opacity="0.32"
|
||||
ShadowDepth="1" />
|
||||
</Button.Effect>
|
||||
</Button>
|
||||
|
||||
<Border
|
||||
HorizontalAlignment="Left"
|
||||
Grid.Row="1"
|
||||
Margin="40,0,0,0"
|
||||
BorderThickness="2"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="5">
|
||||
<StackPanel
|
||||
Orientation="Horizontal">
|
||||
<Grid>
|
||||
<TextBox
|
||||
x:Name="SearchTextBox"
|
||||
Width="320"
|
||||
Text="{Binding SearchTerm, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource PrimaryBorderBrush}"
|
||||
ToolTip="{x:Static props:Resources.SearchExplanation}"
|
||||
/>
|
||||
<TextBlock
|
||||
IsHitTestVisible="False"
|
||||
Text="{x:Static props:Resources.Search}"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{DynamicResource SecondaryForegroundBrush}"
|
||||
ToolTip="{x:Static props:Resources.SearchExplanation}"
|
||||
Margin="10,0,0,0">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Text, ElementName=SearchTextBox}" Value="">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Margin="-50,0,34,0"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Search}"
|
||||
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||
Foreground="{DynamicResource SecondaryForegroundBrush}"
|
||||
Text="" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal"
|
||||
Margin="0,0,40,0">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Margin="10,0,10,0"
|
||||
Text="{x:Static props:Resources.SortBy}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
/>
|
||||
<ComboBox
|
||||
Width="140"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource PrimaryBorderBrush}"
|
||||
SelectedIndex="{Binding OrderByIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
|
||||
<ComboBoxItem Content="{x:Static props:Resources.LastLaunched}" />
|
||||
<ComboBoxItem Content="{x:Static props:Resources.Created}" />
|
||||
<ComboBoxItem Content="{x:Static props:Resources.Name}" />
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Text="{Binding EmptyProjectsViewMessage, UpdateSourceTrigger=PropertyChanged}"
|
||||
FontSize="20"
|
||||
Foreground="{DynamicResource SecondaryForegroundBrush}"
|
||||
TextAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{Binding IsProjectsViewEmpty, Mode=OneWay, Converter={StaticResource BoolToVis}, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
<ScrollViewer
|
||||
VerticalContentAlignment="Stretch"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
Grid.Row="2"
|
||||
Margin="40,15,40,40"
|
||||
Visibility="{Binding IsProjectsViewEmpty, Mode=OneWay, Converter={StaticResource BooleanToInvertedVisibilityConverter}, UpdateSourceTrigger=PropertyChanged}">
|
||||
<ItemsControl ItemsSource="{Binding ProjectsView, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel
|
||||
IsItemsHost="True"
|
||||
Orientation="Vertical"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="models:Project">
|
||||
<Button
|
||||
x:Name="EditButton"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Edit}"
|
||||
Margin="0,12,0,0"
|
||||
Click="EditButtonClicked"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
Padding="1">
|
||||
<Border Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
HorizontalAlignment="Stretch"
|
||||
CornerRadius="5">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="110" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Left" Margin="12,14,10,10">
|
||||
<TextBlock
|
||||
Text="{Binding Name, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"
|
||||
FontSize="16"
|
||||
Margin="0,0,0,8"
|
||||
FontWeight="SemiBold"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"/>
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,0,8" >
|
||||
<Image
|
||||
Source="{Binding PreviewIcons, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Height="20" />
|
||||
<TextBlock
|
||||
Text="{Binding AppsCountString}"
|
||||
Margin="6,0,4,0"
|
||||
VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock
|
||||
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Text=""
|
||||
Margin="0,3,10,0"/>
|
||||
<TextBlock Text="{Binding LastLaunched, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Vertical" Grid.Column="1" Margin="12,12,12,12">
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right">
|
||||
<Button
|
||||
x:Name="MoreButton"
|
||||
HorizontalAlignment="Right"
|
||||
Style="{StaticResource IconOnlyButtonStyle}"
|
||||
Click="MoreButton_Click">
|
||||
<TextBlock
|
||||
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Text=""/>
|
||||
</Button>
|
||||
<Popup
|
||||
IsOpen="{Binding IsPopupVisible, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
StaysOpen="False"
|
||||
AllowsTransparency="True"
|
||||
PlacementTarget="{Binding ElementName=MoreButton}"
|
||||
Placement="Left">
|
||||
<Grid
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}">
|
||||
<Grid.OpacityMask>
|
||||
<VisualBrush Visual="{Binding ElementName=OpacityBorder}" />
|
||||
</Grid.OpacityMask>
|
||||
<Border
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
x:Name="OpacityBorder"
|
||||
Background="Black"
|
||||
CornerRadius="5" />
|
||||
<StackPanel
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}"
|
||||
Orientation="Vertical">
|
||||
<Button
|
||||
Style="{StaticResource DeleteButtonStyle}"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Edit}"
|
||||
Click="EditButtonClicked">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
AutomationProperties.Name="{x:Static props:Resources.Edit}"
|
||||
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Text="" />
|
||||
<TextBlock
|
||||
Margin="10,0,0,0"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Edit}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Text="{x:Static props:Resources.Edit}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button
|
||||
Style="{StaticResource DeleteButtonStyle}"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Delete}"
|
||||
Click="DeleteButtonClicked">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
AutomationProperties.Name="{x:Static props:Resources.Delete}"
|
||||
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Text="" />
|
||||
<TextBlock
|
||||
Margin="10,0,0,0"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Delete}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Text="{x:Static props:Resources.Delete}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Popup>
|
||||
</StackPanel>
|
||||
<Button
|
||||
Padding="20,4,20,4"
|
||||
Margin="0,6,0,0"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Launch}"
|
||||
Content="{x:Static props:Resources.Launch}"
|
||||
HorizontalAlignment="Right"
|
||||
Background="{DynamicResource TertiaryBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource SecondaryBorderBrush}"
|
||||
BorderThickness="1"
|
||||
Click="LaunchButton_Click"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -1,63 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using ProjectsEditor.Models;
|
||||
using ProjectsEditor.ViewModels;
|
||||
|
||||
namespace ProjectsEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainPage.xaml
|
||||
/// </summary>
|
||||
public partial class MainPage : Page
|
||||
{
|
||||
private MainViewModel _mainViewModel;
|
||||
|
||||
public MainPage(MainViewModel mainViewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
_mainViewModel = mainViewModel;
|
||||
this.DataContext = _mainViewModel;
|
||||
}
|
||||
|
||||
private /*async*/ void NewProjectButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_mainViewModel.AddNewProject();
|
||||
}
|
||||
|
||||
private void EditButtonClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_mainViewModel.CloseAllPopups();
|
||||
Button button = sender as Button;
|
||||
Project selectedProject = button.DataContext as Project;
|
||||
_mainViewModel.EditProject(selectedProject);
|
||||
}
|
||||
|
||||
private void DeleteButtonClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
Button button = sender as Button;
|
||||
Project selectedProject = button.DataContext as Project;
|
||||
_mainViewModel.DeleteProject(selectedProject);
|
||||
}
|
||||
|
||||
private void MoreButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
Button button = sender as Button;
|
||||
Project project = button.DataContext as Project;
|
||||
project.IsPopupVisible = true;
|
||||
}
|
||||
|
||||
private void LaunchButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
Button button = sender as Button;
|
||||
Project project = button.DataContext as Project;
|
||||
_mainViewModel.LaunchProject(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<Window
|
||||
x:Class="ProjectsEditor.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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:props="clr-namespace:ProjectsEditor.Properties"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
x:Name="ProjectsMainWindow"
|
||||
Title="{x:Static props:Resources.MainTitle}"
|
||||
ui:TitleBar.Background="{DynamicResource PrimaryBackgroundBrush}"
|
||||
ui:TitleBar.InactiveBackground="{DynamicResource TertiaryBackgroundBrush}"
|
||||
ui:TitleBar.IsIconVisible="True"
|
||||
ui:WindowHelper.UseModernWindowStyle="True"
|
||||
MinWidth="700"
|
||||
MinHeight="680"
|
||||
AutomationProperties.Name="Projects Editor"
|
||||
Closing="OnClosing"
|
||||
ContentRendered="OnContentRendered"
|
||||
ResizeMode="CanResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
mc:Ignorable="d"
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}">
|
||||
<Border
|
||||
CornerRadius="20"
|
||||
BorderThickness="1">
|
||||
<Grid Margin="0,10,0,0">
|
||||
<Frame
|
||||
x:Name="ContentFrame"
|
||||
NavigationUIVisibility="Hidden"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
||||
@@ -1,100 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using ProjectsEditor.Utils;
|
||||
using ProjectsEditor.ViewModels;
|
||||
|
||||
namespace ProjectsEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private bool haveTriedToGetFocusAlready;
|
||||
|
||||
public MainViewModel MainViewModel { get; set; }
|
||||
|
||||
private static MainPage _mainPage;
|
||||
|
||||
public MainWindow(MainViewModel mainViewModel)
|
||||
{
|
||||
MainViewModel = mainViewModel;
|
||||
mainViewModel.SetMainWindow(this);
|
||||
InitializeComponent();
|
||||
|
||||
_mainPage = new MainPage(mainViewModel);
|
||||
|
||||
ContentFrame.Navigate(_mainPage);
|
||||
|
||||
MaxWidth = SystemParameters.PrimaryScreenWidth;
|
||||
MaxHeight = SystemParameters.PrimaryScreenHeight;
|
||||
}
|
||||
|
||||
private void BringToFront()
|
||||
{
|
||||
// Get the window handle of the Projects Editor window
|
||||
IntPtr handle = new WindowInteropHelper(this).Handle;
|
||||
|
||||
// Get the handle of the window currently in the foreground
|
||||
IntPtr foregroundWindowHandle = NativeMethods.GetForegroundWindow();
|
||||
|
||||
// Get the thread IDs of the current thread and the thread of the foreground window
|
||||
uint currentThreadId = NativeMethods.GetCurrentThreadId();
|
||||
uint activeThreadId = NativeMethods.GetWindowThreadProcessId(foregroundWindowHandle, IntPtr.Zero);
|
||||
|
||||
// Check if the active thread is different from the current thread
|
||||
if (activeThreadId != currentThreadId)
|
||||
{
|
||||
// Attach the input processing mechanism of the current thread to the active thread
|
||||
NativeMethods.AttachThreadInput(activeThreadId, currentThreadId, true);
|
||||
|
||||
// Set the Projects Editor window as the foreground window
|
||||
NativeMethods.SetForegroundWindow(handle);
|
||||
|
||||
// Detach the input processing mechanism of the current thread from the active thread
|
||||
NativeMethods.AttachThreadInput(activeThreadId, currentThreadId, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the Projects Editor window as the foreground window
|
||||
NativeMethods.SetForegroundWindow(handle);
|
||||
}
|
||||
|
||||
// Bring the Projects Editor window to the foreground and activate it
|
||||
NativeMethods.SwitchToThisWindow(handle, true);
|
||||
|
||||
haveTriedToGetFocusAlready = true;
|
||||
}
|
||||
|
||||
private void OnClosing(object sender, EventArgs e)
|
||||
{
|
||||
App.Current.Shutdown();
|
||||
}
|
||||
|
||||
// This is required to fix a WPF rendering bug when using custom chrome
|
||||
private void OnContentRendered(object sender, EventArgs e)
|
||||
{
|
||||
if (!haveTriedToGetFocusAlready)
|
||||
{
|
||||
BringToFront();
|
||||
}
|
||||
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
public void ShowPage(ProjectEditor editPage)
|
||||
{
|
||||
ContentFrame.Navigate(editPage);
|
||||
}
|
||||
|
||||
public void SwitchToMainView()
|
||||
{
|
||||
ContentFrame.GoBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// 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.
|
||||
|
||||
namespace ProjectsEditor.Models
|
||||
{
|
||||
public sealed class AppListDataTemplateSelector : System.Windows.Controls.DataTemplateSelector
|
||||
{
|
||||
public System.Windows.DataTemplate HeaderTemplate { get; set; }
|
||||
|
||||
public System.Windows.DataTemplate AppTemplate { get; set; }
|
||||
|
||||
public AppListDataTemplateSelector()
|
||||
{
|
||||
HeaderTemplate = new System.Windows.DataTemplate();
|
||||
AppTemplate = new System.Windows.DataTemplate();
|
||||
}
|
||||
|
||||
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
|
||||
{
|
||||
if (item is string)
|
||||
{
|
||||
return HeaderTemplate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AppTemplate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media.Imaging;
|
||||
using ManagedCommon;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Management.Deployment;
|
||||
|
||||
namespace ProjectsEditor.Models
|
||||
{
|
||||
public class Application : INotifyPropertyChanged, IDisposable
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public Project Parent { get; set; }
|
||||
|
||||
public struct WindowPosition
|
||||
{
|
||||
public int X { get; set; }
|
||||
|
||||
public int Y { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
}
|
||||
|
||||
public string AppName { get; set; }
|
||||
|
||||
public string AppPath { get; set; }
|
||||
|
||||
public string AppTitle { get; set; }
|
||||
|
||||
public string PackageFullName { get; set; }
|
||||
|
||||
public string CommandLineArguments { get; set; }
|
||||
|
||||
public bool Minimized { get; set; }
|
||||
|
||||
public bool Maximized { get; set; }
|
||||
|
||||
private bool _isNotFound;
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsNotFound
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isNotFound;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_isNotFound != value)
|
||||
{
|
||||
_isNotFound = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsNotFound)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsSelected { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsHighlighted { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public int RepeatIndex { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string RepeatIndexString
|
||||
{
|
||||
get
|
||||
{
|
||||
return RepeatIndex == 0 ? string.Empty : RepeatIndex.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
private Icon _icon = null;
|
||||
|
||||
[JsonIgnore]
|
||||
public Icon Icon
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_icon == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(AppPath) && IsPackagedApp)
|
||||
{
|
||||
Task<AppListEntry> task = Task.Run<AppListEntry>(async () => await GetAppByPackageFamilyNameAsync());
|
||||
AppListEntry packApp = task.Result;
|
||||
if (packApp == null)
|
||||
{
|
||||
IsNotFound = true;
|
||||
_icon = new Icon(@"images\DefaultIcon.ico");
|
||||
}
|
||||
else
|
||||
{
|
||||
string filename = Path.GetFileName(AppPath);
|
||||
string newExeLocation = Path.Combine(packApp.AppInfo.Package.InstalledPath, filename);
|
||||
_icon = Icon.ExtractAssociatedIcon(newExeLocation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_icon = Icon.ExtractAssociatedIcon(AppPath);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Logger.LogWarning($"Icon not found on app path: {AppPath}. Using default icon");
|
||||
IsNotFound = true;
|
||||
_icon = new Icon(@"images\DefaultIcon.ico");
|
||||
}
|
||||
}
|
||||
|
||||
return _icon;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<AppListEntry> GetAppByPackageFamilyNameAsync()
|
||||
{
|
||||
var pkgManager = new PackageManager();
|
||||
var pkg = pkgManager.FindPackagesForUser(string.Empty, PackagedId).FirstOrDefault();
|
||||
|
||||
if (pkg == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var apps = await pkg.GetAppListEntriesAsync();
|
||||
if (apps == null || apps.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
AppListEntry firstApp = apps[0];
|
||||
|
||||
// RandomAccessStreamReference stream = firstApp.AppInfo.DisplayInfo.GetLogo(new Windows.Foundation.Size(64, 64));
|
||||
// IRandomAccessStreamWithContentType content = await stream.OpenReadAsync();
|
||||
// BitmapImage bitmapImage = new BitmapImage();
|
||||
// bitmapImage.StreamSource = (Stream)content;
|
||||
return firstApp;
|
||||
}
|
||||
|
||||
private BitmapImage _iconBitmapImage;
|
||||
|
||||
public BitmapImage IconBitmapImage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_iconBitmapImage == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Bitmap previewBitmap = new Bitmap(32, 32);
|
||||
using (Graphics graphics = Graphics.FromImage(previewBitmap))
|
||||
{
|
||||
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
graphics.DrawIcon(Icon, new Rectangle(0, 0, 32, 32));
|
||||
}
|
||||
|
||||
using (var memory = new MemoryStream())
|
||||
{
|
||||
previewBitmap.Save(memory, ImageFormat.Png);
|
||||
memory.Position = 0;
|
||||
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.StreamSource = memory;
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapImage.EndInit();
|
||||
bitmapImage.Freeze();
|
||||
|
||||
_iconBitmapImage = bitmapImage;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception while drawing icon for app with path: {AppPath}. Exception message: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
return _iconBitmapImage;
|
||||
}
|
||||
}
|
||||
|
||||
public WindowPosition Position { get; set; }
|
||||
|
||||
private WindowPosition? _scaledPosition;
|
||||
|
||||
public WindowPosition ScaledPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_scaledPosition == null)
|
||||
{
|
||||
double scaleFactor = MonitorSetup.Dpi / 96.0;
|
||||
_scaledPosition = new WindowPosition()
|
||||
{
|
||||
X = (int)(scaleFactor * Position.X),
|
||||
Y = (int)(scaleFactor * Position.Y),
|
||||
Height = (int)(scaleFactor * Position.Height),
|
||||
Width = (int)(scaleFactor * Position.Width),
|
||||
};
|
||||
}
|
||||
|
||||
return _scaledPosition.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MonitorNumber { get; set; }
|
||||
|
||||
private MonitorSetup _monitorSetup;
|
||||
|
||||
public MonitorSetup MonitorSetup
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_monitorSetup == null)
|
||||
{
|
||||
_monitorSetup = Parent.Monitors.Where(x => x.MonitorNumber == MonitorNumber).FirstOrDefault();
|
||||
}
|
||||
|
||||
return _monitorSetup;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPropertyChanged(PropertyChangedEventArgs e)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private bool? _isPackagedApp;
|
||||
|
||||
public string PackagedId { get; set; }
|
||||
|
||||
public string PackagedName { get; set; }
|
||||
|
||||
public string PackagedPublisherID { get; set; }
|
||||
|
||||
public string Aumid { get; set; }
|
||||
|
||||
public bool IsPackagedApp
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_isPackagedApp == null)
|
||||
{
|
||||
if (!AppPath.StartsWith("C:\\Program Files\\WindowsApps\\", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
_isPackagedApp = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
string appPath = AppPath.Replace("C:\\Program Files\\WindowsApps\\", string.Empty);
|
||||
Regex packagedAppPathRegex = new Regex(@"(?<APPID>[^_]*)_\d+.\d+.\d+.\d+_x64__(?<PublisherID>[^\\]*)", RegexOptions.ExplicitCapture | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||
Match match = packagedAppPathRegex.Match(appPath);
|
||||
_isPackagedApp = match.Success;
|
||||
if (match.Success)
|
||||
{
|
||||
PackagedName = match.Groups["APPID"].Value;
|
||||
PackagedPublisherID = match.Groups["PublisherID"].Value;
|
||||
PackagedId = $"{PackagedName}_{PackagedPublisherID}";
|
||||
Aumid = $"{PackagedId}!App";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _isPackagedApp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.Windows;
|
||||
|
||||
namespace ProjectsEditor.Models
|
||||
{
|
||||
public class Monitor
|
||||
{
|
||||
public string MonitorName { get; private set; }
|
||||
|
||||
public string MonitorInstanceId { get; private set; }
|
||||
|
||||
public int MonitorNumber { get; private set; }
|
||||
|
||||
public int Dpi { get; private set; }
|
||||
|
||||
public Rect MonitorDpiUnawareBounds { get; private set; }
|
||||
|
||||
public Rect MonitorDpiAwareBounds { get; private set; }
|
||||
|
||||
public Monitor(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds)
|
||||
{
|
||||
MonitorName = monitorName;
|
||||
MonitorInstanceId = monitorInstanceId;
|
||||
MonitorNumber = number;
|
||||
Dpi = dpi;
|
||||
MonitorDpiAwareBounds = dpiAwareBounds;
|
||||
MonitorDpiUnawareBounds = dpiUnawareBounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace ProjectsEditor.Models
|
||||
{
|
||||
public class MonitorSetup : Monitor, INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(PropertyChangedEventArgs e)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
public string MonitorInfo { get => MonitorName; }
|
||||
|
||||
public string MonitorInfoWithResolution { get => $"{MonitorName} {MonitorDpiAwareBounds.Width}x{MonitorDpiAwareBounds.Height}"; }
|
||||
|
||||
public MonitorSetup(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds)
|
||||
: base(monitorName, monitorInstanceId, number, dpi, dpiAwareBounds, dpiUnawareBounds)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media.Imaging;
|
||||
using ManagedCommon;
|
||||
using ProjectsEditor.Utils;
|
||||
|
||||
namespace ProjectsEditor.Models
|
||||
{
|
||||
public class Project : INotifyPropertyChanged
|
||||
{
|
||||
[JsonIgnore]
|
||||
public string EditorWindowTitle { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
private string _name;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_name = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Name)));
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(CanBeSaved)));
|
||||
}
|
||||
}
|
||||
|
||||
public long CreationTime { get; set; } // in seconds
|
||||
|
||||
public long LastLaunchedTime { get; set; } // in seconds
|
||||
|
||||
public bool IsShortcutNeeded { get; set; }
|
||||
|
||||
public string LastLaunched
|
||||
{
|
||||
get
|
||||
{
|
||||
string lastLaunched = ProjectsEditor.Properties.Resources.LastLaunched + ": ";
|
||||
if (LastLaunchedTime == 0)
|
||||
{
|
||||
return lastLaunched + ProjectsEditor.Properties.Resources.Never;
|
||||
}
|
||||
|
||||
const int SECOND = 1;
|
||||
const int MINUTE = 60 * SECOND;
|
||||
const int HOUR = 60 * MINUTE;
|
||||
const int DAY = 24 * HOUR;
|
||||
const int MONTH = 30 * DAY;
|
||||
|
||||
DateTime lastLaunchDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(LastLaunchedTime);
|
||||
|
||||
var now = DateTime.UtcNow.Ticks;
|
||||
var ts = DateTime.UtcNow - lastLaunchDateTime;
|
||||
double delta = Math.Abs(ts.TotalSeconds);
|
||||
|
||||
if (delta < 1 * MINUTE)
|
||||
{
|
||||
return lastLaunched + ProjectsEditor.Properties.Resources.Recently;
|
||||
}
|
||||
|
||||
if (delta < 2 * MINUTE)
|
||||
{
|
||||
return lastLaunched + ProjectsEditor.Properties.Resources.OneMinuteAgo;
|
||||
}
|
||||
|
||||
if (delta < 45 * MINUTE)
|
||||
{
|
||||
return lastLaunched + ts.Minutes + " " + ProjectsEditor.Properties.Resources.MinutesAgo;
|
||||
}
|
||||
|
||||
if (delta < 90 * MINUTE)
|
||||
{
|
||||
return lastLaunched + ProjectsEditor.Properties.Resources.OneHourAgo;
|
||||
}
|
||||
|
||||
if (delta < 24 * HOUR)
|
||||
{
|
||||
return lastLaunched + ts.Hours + " " + ProjectsEditor.Properties.Resources.HoursAgo;
|
||||
}
|
||||
|
||||
if (delta < 48 * HOUR)
|
||||
{
|
||||
return lastLaunched + ProjectsEditor.Properties.Resources.Yesterday;
|
||||
}
|
||||
|
||||
if (delta < 30 * DAY)
|
||||
{
|
||||
return lastLaunched + ts.Days + " " + ProjectsEditor.Properties.Resources.DaysAgo;
|
||||
}
|
||||
|
||||
if (delta < 12 * MONTH)
|
||||
{
|
||||
int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
|
||||
return lastLaunched + (months <= 1 ? ProjectsEditor.Properties.Resources.OneMonthAgo : months + " " + ProjectsEditor.Properties.Resources.MonthsAgo);
|
||||
}
|
||||
else
|
||||
{
|
||||
int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
|
||||
return lastLaunched + (years <= 1 ? ProjectsEditor.Properties.Resources.OneYearAgo : years + " " + ProjectsEditor.Properties.Resources.YearsAgo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanBeSaved
|
||||
{
|
||||
get => Name.Length > 0 && Applications.Where(x => x.IsSelected).Any();
|
||||
}
|
||||
|
||||
private bool _isPopupVisible;
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsPopupVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isPopupVisible;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_isPopupVisible = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsPopupVisible)));
|
||||
}
|
||||
}
|
||||
|
||||
public List<Application> Applications { get; set; }
|
||||
|
||||
public List<object> ApplicationsListed
|
||||
{
|
||||
get
|
||||
{
|
||||
List<object> applicationsListed = new List<object>();
|
||||
ILookup<MonitorSetup, Application> apps = Applications.Where(x => !x.Minimized).ToLookup(x => x.MonitorSetup);
|
||||
foreach (var appItem in apps.OrderBy(x => x.Key.MonitorDpiUnawareBounds.Left).ThenBy(x => x.Key.MonitorDpiUnawareBounds.Top))
|
||||
{
|
||||
applicationsListed.Add(appItem.Key.MonitorInfo);
|
||||
foreach (Application app in appItem)
|
||||
{
|
||||
applicationsListed.Add(app);
|
||||
}
|
||||
}
|
||||
|
||||
var minimizedApps = Applications.Where(x => x.Minimized);
|
||||
if (minimizedApps.Any())
|
||||
{
|
||||
applicationsListed.Add("Minimized Apps");
|
||||
foreach (Application app in minimizedApps)
|
||||
{
|
||||
applicationsListed.Add(app);
|
||||
}
|
||||
}
|
||||
|
||||
return applicationsListed;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public string AppsCountString
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = Applications.Where(x => x.IsSelected).Count();
|
||||
return count.ToString(CultureInfo.InvariantCulture) + " " + (count == 1 ? Properties.Resources.App : Properties.Resources.Apps);
|
||||
}
|
||||
}
|
||||
|
||||
public List<MonitorSetup> Monitors { get; set; }
|
||||
|
||||
private BitmapImage _previewIcons;
|
||||
private BitmapImage _previewImage;
|
||||
private double _previewImageWidth;
|
||||
|
||||
public Project(Project selectedProject)
|
||||
{
|
||||
Name = selectedProject.Name;
|
||||
PreviewIcons = selectedProject.PreviewIcons;
|
||||
PreviewImage = selectedProject.PreviewImage;
|
||||
IsShortcutNeeded = selectedProject.IsShortcutNeeded;
|
||||
|
||||
int screenIndex = 1;
|
||||
|
||||
Monitors = new List<MonitorSetup>();
|
||||
foreach (var item in selectedProject.Monitors.OrderBy(x => x.MonitorDpiAwareBounds.Left).ThenBy(x => x.MonitorDpiAwareBounds.Top))
|
||||
{
|
||||
Monitors.Add(new MonitorSetup($"Screen {screenIndex}", item.MonitorInstanceId, item.MonitorNumber, item.Dpi, item.MonitorDpiAwareBounds, item.MonitorDpiUnawareBounds));
|
||||
screenIndex++;
|
||||
}
|
||||
|
||||
Applications = new List<Application>();
|
||||
foreach (var item in selectedProject.Applications)
|
||||
{
|
||||
Applications.Add(new Application()
|
||||
{
|
||||
AppName = item.AppName,
|
||||
AppPath = item.AppPath,
|
||||
AppTitle = item.AppTitle,
|
||||
CommandLineArguments = item.CommandLineArguments,
|
||||
PackageFullName = item.PackageFullName,
|
||||
Minimized = item.Minimized,
|
||||
Maximized = item.Maximized,
|
||||
IsSelected = item.IsSelected,
|
||||
MonitorNumber = item.MonitorNumber,
|
||||
IsNotFound = item.IsNotFound,
|
||||
Position = new Application.WindowPosition() { X = item.Position.X, Y = item.Position.Y, Height = item.Position.Height, Width = item.Position.Width },
|
||||
Parent = this,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public Project()
|
||||
{
|
||||
}
|
||||
|
||||
public BitmapImage PreviewIcons
|
||||
{
|
||||
get
|
||||
{
|
||||
return _previewIcons;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_previewIcons = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(PreviewIcons)));
|
||||
}
|
||||
}
|
||||
|
||||
public BitmapImage PreviewImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return _previewImage;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_previewImage = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(PreviewImage)));
|
||||
}
|
||||
}
|
||||
|
||||
public double PreviewImageWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return _previewImageWidth;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_previewImageWidth = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(PreviewImageWidth)));
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged(PropertyChangedEventArgs e)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
public async void Initialize()
|
||||
{
|
||||
PreviewIcons = await Task.Run(() => DrawHelper.DrawPreviewIcons(this));
|
||||
Rectangle commonBounds = GetCommonBounds();
|
||||
PreviewImage = await Task.Run(() => DrawHelper.DrawPreview(this, commonBounds));
|
||||
PreviewImageWidth = commonBounds.Width / (commonBounds.Height * 1.2 / 200);
|
||||
}
|
||||
|
||||
private Rectangle GetCommonBounds()
|
||||
{
|
||||
double minX = Monitors.First().MonitorDpiAwareBounds.Left;
|
||||
double minY = Monitors.First().MonitorDpiAwareBounds.Top;
|
||||
double maxX = Monitors.First().MonitorDpiAwareBounds.Right;
|
||||
double maxY = Monitors.First().MonitorDpiAwareBounds.Bottom;
|
||||
for (int monitorIndex = 1; monitorIndex < Monitors.Count; monitorIndex++)
|
||||
{
|
||||
Monitor monitor = Monitors[monitorIndex];
|
||||
minX = Math.Min(minX, monitor.MonitorDpiAwareBounds.Left);
|
||||
minY = Math.Min(minY, monitor.MonitorDpiAwareBounds.Top);
|
||||
maxX = Math.Max(maxX, monitor.MonitorDpiAwareBounds.Right);
|
||||
maxY = Math.Max(maxY, monitor.MonitorDpiAwareBounds.Bottom);
|
||||
}
|
||||
|
||||
return new Rectangle((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
<Page x:Class="ProjectsEditor.ProjectEditor"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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:props="clr-namespace:ProjectsEditor.Properties"
|
||||
xmlns:local="clr-namespace:ProjectsEditor"
|
||||
xmlns:models="clr-namespace:ProjectsEditor.Models"
|
||||
mc:Ignorable="d"
|
||||
Title="Project Editor"
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}">
|
||||
<Page.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis" />
|
||||
|
||||
<DataTemplate x:Key="headerTemplate">
|
||||
<Border>
|
||||
<TextBlock
|
||||
Text="{Binding .}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
Margin="0,20,20,5"
|
||||
VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="appTemplate">
|
||||
<Border
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
MouseEnter="AppBorder_MouseEnter"
|
||||
MouseLeave="AppBorder_MouseLeave">
|
||||
<Grid Margin="5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="3*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Text=""
|
||||
Foreground="#EED202"
|
||||
FontSize="14"
|
||||
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||
FontWeight="Normal"
|
||||
Margin="5 0 0 0"
|
||||
ToolTip="{x:Static props:Resources.NotFoundTooltip}"
|
||||
Visibility="{Binding IsNotFound, Converter={StaticResource BoolToVis}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
VerticalAlignment="Center"/>
|
||||
<Image
|
||||
Grid.Column="1"
|
||||
Width="20"
|
||||
Height="20"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Margin="10"
|
||||
Source="{Binding IconBitmapImage}"/>
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
Text="{Binding RepeatIndexString, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
Width="20"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBlock
|
||||
Grid.Column="3"
|
||||
Text="{Binding AppName}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox
|
||||
x:Name="CommandLineTextBox"
|
||||
Grid.Column="4"
|
||||
Text="{Binding CommandLineArguments, Mode=TwoWay}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Background="{DynamicResource TertiaryBackgroundBrush}"
|
||||
BorderThickness="0"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBlock
|
||||
Grid.Column="4"
|
||||
IsHitTestVisible="False"
|
||||
Text="{x:Static props:Resources.WriteArgs}"
|
||||
Foreground="{DynamicResource SecondaryForegroundBrush}"
|
||||
Background="{DynamicResource TertiaryBackgroundBrush}"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
VerticalAlignment="Center"
|
||||
Margin="12,0,12,0">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Text, ElementName=CommandLineTextBox}" Value="">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<CheckBox
|
||||
Grid.Column="5"
|
||||
IsChecked="{Binding IsSelected, Mode=TwoWay}"
|
||||
Checked="CheckBox_Checked"
|
||||
Unchecked="CheckBox_Checked"
|
||||
Margin="10"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
<models:AppListDataTemplateSelector
|
||||
HeaderTemplate="{StaticResource headerTemplate}"
|
||||
AppTemplate="{StaticResource appTemplate}"
|
||||
x:Key="AppListDataTemplateSelector"/>
|
||||
</Page.Resources>
|
||||
<Grid Margin="40,0,40,40">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
<Button
|
||||
Margin="0,20,0,20"
|
||||
Click="CancelButtonClicked"
|
||||
Background="Transparent"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock
|
||||
Text="{x:Static props:Resources.Projects}"
|
||||
FontSize="24"
|
||||
FontWeight="Normal"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
VerticalAlignment="Center"/>
|
||||
</Button>
|
||||
<TextBlock
|
||||
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
FontSize="16"
|
||||
Margin="10,0,0,0"
|
||||
Text=""
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBlock
|
||||
Text="{Binding EditorWindowTitle}"
|
||||
FontSize="24"
|
||||
FontWeight="SemiBold"
|
||||
Margin="10,0,0,0"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="1" Orientation="Vertical">
|
||||
<TextBlock Text="{x:Static props:Resources.ProjectName}" FontSize="14" FontWeight="Normal" Foreground="{DynamicResource PrimaryForegroundBrush}"/>
|
||||
<TextBox
|
||||
x:Name="EditNameTextBox"
|
||||
Width="320"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource PrimaryBorderBrush}"
|
||||
BorderThickness="2"
|
||||
Margin="0,6,0,6"
|
||||
HorizontalAlignment="Left"
|
||||
GotFocus="EditNameTextBox_GotFocus"
|
||||
TextChanged="EditNameTextBox_TextChanged"
|
||||
KeyDown="EditNameTextBoxKeyDown" />
|
||||
</StackPanel>
|
||||
<Border
|
||||
Grid.Row="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource MonitorViewBackgroundBrush}"
|
||||
CornerRadius="5">
|
||||
<Image
|
||||
Width="{Binding PreviewImageWidth, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Height="200"
|
||||
Source="{Binding PreviewImage, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Stretch="Fill"
|
||||
Margin="2"/>
|
||||
</Border>
|
||||
<ScrollViewer
|
||||
Margin="0,10,0,0"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
Grid.Row="3">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding ApplicationsListed, Mode=OneWay}"
|
||||
ItemTemplateSelector="{StaticResource AppListDataTemplateSelector}">
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
<DockPanel Grid.Row="4" Margin="0,20,0,20">
|
||||
<CheckBox
|
||||
DockPanel.Dock="Left"
|
||||
Content="{x:Static props:Resources.CreateShortcut}"
|
||||
IsChecked="{Binding IsShortcutNeeded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
FontSize="14"/>
|
||||
<StackPanel
|
||||
DockPanel.Dock="Right"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="40,0,0,0">
|
||||
<Button
|
||||
x:Name="CancelButton"
|
||||
Margin="20,0,0,0"
|
||||
Height="36"
|
||||
Padding="24,0,24,0"
|
||||
Content="{x:Static props:Resources.Cancel}"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Cancel}"
|
||||
Click="CancelButtonClicked">
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="SaveButton"
|
||||
Margin="20,0,0,0"
|
||||
Padding="24,0,24,0"
|
||||
Height="36"
|
||||
IsEnabled="{Binding CanBeSaved, UpdateSourceTrigger=PropertyChanged}"
|
||||
Content="{x:Static props:Resources.Save_project}"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Save_project}"
|
||||
Click="SaveButtonClicked"
|
||||
Style="{StaticResource AccentButtonStyle}">
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -1,95 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using ProjectsEditor.Models;
|
||||
using ProjectsEditor.ViewModels;
|
||||
|
||||
namespace ProjectsEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ProjectEditor.xaml
|
||||
/// </summary>
|
||||
public partial class ProjectEditor : Page
|
||||
{
|
||||
private MainViewModel _mainViewModel;
|
||||
|
||||
public ProjectEditor(MainViewModel mainViewModel)
|
||||
{
|
||||
_mainViewModel = mainViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void CheckBox_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CheckBox checkBox = sender as CheckBox;
|
||||
Models.Application application = checkBox.DataContext as Models.Application;
|
||||
Models.Project project = application.Parent;
|
||||
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.CanBeSaved)));
|
||||
project.Initialize();
|
||||
}
|
||||
|
||||
private void SaveButtonClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Project projectToSave = this.DataContext as Project;
|
||||
_mainViewModel.SaveProject(projectToSave);
|
||||
_mainViewModel.SwitchToMainView();
|
||||
}
|
||||
|
||||
private void CancelButtonClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_mainViewModel.CancelLastEdit();
|
||||
_mainViewModel.SwitchToMainView();
|
||||
}
|
||||
|
||||
private void EditNameTextBoxKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
e.Handled = true;
|
||||
Project project = this.DataContext as Project;
|
||||
project.Name = EditNameTextBox.Text;
|
||||
}
|
||||
else if (e.Key == Key.Escape)
|
||||
{
|
||||
e.Handled = true;
|
||||
Project project = this.DataContext as Project;
|
||||
_mainViewModel.CancelProjectName(project);
|
||||
}
|
||||
}
|
||||
|
||||
private void EditNameTextBox_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_mainViewModel.SaveProjectName(DataContext as Project);
|
||||
}
|
||||
|
||||
private void AppBorder_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
Border border = sender as Border;
|
||||
Models.Application app = border.DataContext as Models.Application;
|
||||
app.IsHighlighted = true;
|
||||
Project project = app.Parent;
|
||||
project.Initialize();
|
||||
}
|
||||
|
||||
private void AppBorder_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
Border border = sender as Border;
|
||||
Models.Application app = border.DataContext as Models.Application;
|
||||
app.IsHighlighted = false;
|
||||
Project project = app.Parent;
|
||||
project.Initialize();
|
||||
}
|
||||
|
||||
private void EditNameTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
Project project = this.DataContext as Project;
|
||||
project.Name = EditNameTextBox.Text;
|
||||
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.CanBeSaved)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
<PropertyGroup>
|
||||
<AssemblyTitle>PowerToys.ProjectsEditor</AssemblyTitle>
|
||||
<AssemblyDescription>PowerToys Projects Editor</AssemblyDescription>
|
||||
<Description>PowerToys Projects Editor</Description>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<UseWPF>true</UseWPF>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)</OutputPath>
|
||||
<SelfContained>true</SelfContained>
|
||||
<Platforms>AnyCPU;x64;ARM64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{367D7543-7DBA-4381-99F1-BF6142A996C4}</ProjectGuid>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>images\Projects.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AssemblyName>PowerToys.ProjectsEditor</AssemblyName>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="images\DefaultIcon.ico" />
|
||||
<None Remove="images\Projects.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="IWshRuntimeLibrary">
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<Guid>f935dc20-1cf0-11d0-adb9-00c04fd58a0b</Guid>
|
||||
<Lcid>0</Lcid>
|
||||
<Isolated>false</Isolated>
|
||||
<EmbedInteropTypes>true</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
<COMReference Include="Shell32">
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<Guid>50a7e9b0-70ef-11d1-b75a-00a0c90564fe</Guid>
|
||||
<Lcid>0</Lcid>
|
||||
<Isolated>false</Isolated>
|
||||
<EmbedInteropTypes>true</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="images\DefaultIcon.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="images\Projects.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ControlzEx" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="ModernWpfUI" />
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\GPOWrapperProjection\GPOWrapperProjection.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,477 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ProjectsEditor.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ProjectsEditor.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to app.
|
||||
/// </summary>
|
||||
public static string App {
|
||||
get {
|
||||
return ResourceManager.GetString("App", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to App name.
|
||||
/// </summary>
|
||||
public static string App_name {
|
||||
get {
|
||||
return ResourceManager.GetString("App_name", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to apps.
|
||||
/// </summary>
|
||||
public static string Apps {
|
||||
get {
|
||||
return ResourceManager.GetString("Apps", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Are you sure?.
|
||||
/// </summary>
|
||||
public static string Are_You_Sure {
|
||||
get {
|
||||
return ResourceManager.GetString("Are_You_Sure", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Are you sure you want to delete this project?.
|
||||
/// </summary>
|
||||
public static string Are_You_Sure_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Are_You_Sure_Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cancel.
|
||||
/// </summary>
|
||||
public static string Cancel {
|
||||
get {
|
||||
return ResourceManager.GetString("Cancel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Created.
|
||||
/// </summary>
|
||||
public static string Created {
|
||||
get {
|
||||
return ResourceManager.GetString("Created", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create project.
|
||||
/// </summary>
|
||||
public static string CreateProject {
|
||||
get {
|
||||
return ResourceManager.GetString("CreateProject", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create Shortcut.
|
||||
/// </summary>
|
||||
public static string CreateShortcut {
|
||||
get {
|
||||
return ResourceManager.GetString("CreateShortcut", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to days ago.
|
||||
/// </summary>
|
||||
public static string DaysAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("DaysAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remove.
|
||||
/// </summary>
|
||||
public static string Delete {
|
||||
get {
|
||||
return ResourceManager.GetString("Delete", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Delete project dialog..
|
||||
/// </summary>
|
||||
public static string Delete_Project_Dialog_Announce {
|
||||
get {
|
||||
return ResourceManager.GetString("Delete_Project_Dialog_Announce", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit.
|
||||
/// </summary>
|
||||
public static string Edit {
|
||||
get {
|
||||
return ResourceManager.GetString("Edit", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to opened.
|
||||
/// </summary>
|
||||
public static string Edit_Project_Open_Announce {
|
||||
get {
|
||||
return ResourceManager.GetString("Edit_Project_Open_Announce", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit project.
|
||||
/// </summary>
|
||||
public static string EditProject {
|
||||
get {
|
||||
return ResourceManager.GetString("EditProject", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error parsing projects data..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Message {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Message", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to hours ago.
|
||||
/// </summary>
|
||||
public static string HoursAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("HoursAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Last launched.
|
||||
/// </summary>
|
||||
public static string LastLaunched {
|
||||
get {
|
||||
return ResourceManager.GetString("LastLaunched", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Launch.
|
||||
/// </summary>
|
||||
public static string Launch {
|
||||
get {
|
||||
return ResourceManager.GetString("Launch", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Launch args.
|
||||
/// </summary>
|
||||
public static string Launch_args {
|
||||
get {
|
||||
return ResourceManager.GetString("Launch_args", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Projects demo app.
|
||||
/// </summary>
|
||||
public static string MainTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("MainTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to minutes ago.
|
||||
/// </summary>
|
||||
public static string MinutesAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("MinutesAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to months ago.
|
||||
/// </summary>
|
||||
public static string MonthsAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("MonthsAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Name.
|
||||
/// </summary>
|
||||
public static string Name {
|
||||
get {
|
||||
return ResourceManager.GetString("Name", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to never.
|
||||
/// </summary>
|
||||
public static string Never {
|
||||
get {
|
||||
return ResourceManager.GetString("Never", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to New project.
|
||||
/// </summary>
|
||||
public static string New_project {
|
||||
get {
|
||||
return ResourceManager.GetString("New_project", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to There are no saved projects..
|
||||
/// </summary>
|
||||
public static string No_Projects_Message {
|
||||
get {
|
||||
return ResourceManager.GetString("No_Projects_Message", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No projects match the current search..
|
||||
/// </summary>
|
||||
public static string NoProjectsMatch {
|
||||
get {
|
||||
return ResourceManager.GetString("NoProjectsMatch", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The application cannot be found.
|
||||
/// </summary>
|
||||
public static string NotFoundTooltip {
|
||||
get {
|
||||
return ResourceManager.GetString("NotFoundTooltip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to an hour ago.
|
||||
/// </summary>
|
||||
public static string OneHourAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("OneHourAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to a minute ago.
|
||||
/// </summary>
|
||||
public static string OneMinuteAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("OneMinuteAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to one month ago.
|
||||
/// </summary>
|
||||
public static string OneMonthAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("OneMonthAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to one second ago.
|
||||
/// </summary>
|
||||
public static string OneSecondAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("OneSecondAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to one year ago.
|
||||
/// </summary>
|
||||
public static string OneYearAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("OneYearAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Pin Project to Taskbar.
|
||||
/// </summary>
|
||||
public static string PinToTaskbar {
|
||||
get {
|
||||
return ResourceManager.GetString("PinToTaskbar", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Project name.
|
||||
/// </summary>
|
||||
public static string ProjectName {
|
||||
get {
|
||||
return ResourceManager.GetString("ProjectName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Projects.
|
||||
/// </summary>
|
||||
public static string Projects {
|
||||
get {
|
||||
return ResourceManager.GetString("Projects", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to recently.
|
||||
/// </summary>
|
||||
public static string Recently {
|
||||
get {
|
||||
return ResourceManager.GetString("Recently", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Save project.
|
||||
/// </summary>
|
||||
public static string Save_project {
|
||||
get {
|
||||
return ResourceManager.GetString("Save_project", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Search.
|
||||
/// </summary>
|
||||
public static string Search {
|
||||
get {
|
||||
return ResourceManager.GetString("Search", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Search for projects or apps.
|
||||
/// </summary>
|
||||
public static string SearchExplanation {
|
||||
get {
|
||||
return ResourceManager.GetString("SearchExplanation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to seconds ago.
|
||||
/// </summary>
|
||||
public static string SecondsAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("SecondsAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Sort by.
|
||||
/// </summary>
|
||||
public static string SortBy {
|
||||
get {
|
||||
return ResourceManager.GetString("SortBy", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Write arguments here.
|
||||
/// </summary>
|
||||
public static string WriteArgs {
|
||||
get {
|
||||
return ResourceManager.GetString("WriteArgs", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to years ago.
|
||||
/// </summary>
|
||||
public static string YearsAgo {
|
||||
get {
|
||||
return ResourceManager.GetString("YearsAgo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to yesterday.
|
||||
/// </summary>
|
||||
public static string Yesterday {
|
||||
get {
|
||||
return ResourceManager.GetString("Yesterday", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,258 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="App" xml:space="preserve">
|
||||
<value>app</value>
|
||||
</data>
|
||||
<data name="Apps" xml:space="preserve">
|
||||
<value>apps</value>
|
||||
</data>
|
||||
<data name="App_name" xml:space="preserve">
|
||||
<value>App name</value>
|
||||
</data>
|
||||
<data name="Are_You_Sure" xml:space="preserve">
|
||||
<value>Are you sure?</value>
|
||||
</data>
|
||||
<data name="Are_You_Sure_Description" xml:space="preserve">
|
||||
<value>Are you sure you want to delete this project?</value>
|
||||
</data>
|
||||
<data name="Cancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="Created" xml:space="preserve">
|
||||
<value>Created</value>
|
||||
</data>
|
||||
<data name="CreateProject" xml:space="preserve">
|
||||
<value>Create project</value>
|
||||
</data>
|
||||
<data name="CreateShortcut" xml:space="preserve">
|
||||
<value>Create Shortcut</value>
|
||||
</data>
|
||||
<data name="DaysAgo" xml:space="preserve">
|
||||
<value>days ago</value>
|
||||
</data>
|
||||
<data name="Delete" xml:space="preserve">
|
||||
<value>Remove</value>
|
||||
</data>
|
||||
<data name="Delete_Project_Dialog_Announce" xml:space="preserve">
|
||||
<value>Delete project dialog.</value>
|
||||
</data>
|
||||
<data name="Edit" xml:space="preserve">
|
||||
<value>Edit</value>
|
||||
</data>
|
||||
<data name="EditProject" xml:space="preserve">
|
||||
<value>Edit project</value>
|
||||
</data>
|
||||
<data name="Edit_Project_Open_Announce" xml:space="preserve">
|
||||
<value>opened</value>
|
||||
</data>
|
||||
<data name="Error_Parsing_Message" xml:space="preserve">
|
||||
<value>Error parsing projects data.</value>
|
||||
</data>
|
||||
<data name="HoursAgo" xml:space="preserve">
|
||||
<value>hours ago</value>
|
||||
</data>
|
||||
<data name="LastLaunched" xml:space="preserve">
|
||||
<value>Last launched</value>
|
||||
</data>
|
||||
<data name="Launch" xml:space="preserve">
|
||||
<value>Launch</value>
|
||||
</data>
|
||||
<data name="Launch_args" xml:space="preserve">
|
||||
<value>Launch args</value>
|
||||
</data>
|
||||
<data name="MainTitle" xml:space="preserve">
|
||||
<value>Projects demo app</value>
|
||||
</data>
|
||||
<data name="MinutesAgo" xml:space="preserve">
|
||||
<value>minutes ago</value>
|
||||
</data>
|
||||
<data name="MonthsAgo" xml:space="preserve">
|
||||
<value>months ago</value>
|
||||
</data>
|
||||
<data name="Name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="Never" xml:space="preserve">
|
||||
<value>never</value>
|
||||
</data>
|
||||
<data name="New_project" xml:space="preserve">
|
||||
<value>New project</value>
|
||||
</data>
|
||||
<data name="NoProjectsMatch" xml:space="preserve">
|
||||
<value>No projects match the current search.</value>
|
||||
</data>
|
||||
<data name="NotFoundTooltip" xml:space="preserve">
|
||||
<value>The application cannot be found</value>
|
||||
</data>
|
||||
<data name="No_Projects_Message" xml:space="preserve">
|
||||
<value>There are no saved projects.</value>
|
||||
</data>
|
||||
<data name="OneHourAgo" xml:space="preserve">
|
||||
<value>an hour ago</value>
|
||||
</data>
|
||||
<data name="OneMinuteAgo" xml:space="preserve">
|
||||
<value>a minute ago</value>
|
||||
</data>
|
||||
<data name="OneMonthAgo" xml:space="preserve">
|
||||
<value>one month ago</value>
|
||||
</data>
|
||||
<data name="OneSecondAgo" xml:space="preserve">
|
||||
<value>one second ago</value>
|
||||
</data>
|
||||
<data name="OneYearAgo" xml:space="preserve">
|
||||
<value>one year ago</value>
|
||||
</data>
|
||||
<data name="PinToTaskbar" xml:space="preserve">
|
||||
<value>Pin Project to Taskbar</value>
|
||||
</data>
|
||||
<data name="ProjectName" xml:space="preserve">
|
||||
<value>Project name</value>
|
||||
</data>
|
||||
<data name="Projects" xml:space="preserve">
|
||||
<value>Projects</value>
|
||||
</data>
|
||||
<data name="Recently" xml:space="preserve">
|
||||
<value>recently</value>
|
||||
</data>
|
||||
<data name="Save_project" xml:space="preserve">
|
||||
<value>Save project</value>
|
||||
</data>
|
||||
<data name="Search" xml:space="preserve">
|
||||
<value>Search</value>
|
||||
</data>
|
||||
<data name="SearchExplanation" xml:space="preserve">
|
||||
<value>Search for projects or apps</value>
|
||||
</data>
|
||||
<data name="SecondsAgo" xml:space="preserve">
|
||||
<value>seconds ago</value>
|
||||
</data>
|
||||
<data name="SortBy" xml:space="preserve">
|
||||
<value>Sort by</value>
|
||||
</data>
|
||||
<data name="WriteArgs" xml:space="preserve">
|
||||
<value>Write arguments here</value>
|
||||
</data>
|
||||
<data name="YearsAgo" xml:space="preserve">
|
||||
<value>years ago</value>
|
||||
</data>
|
||||
<data name="Yesterday" xml:space="preserve">
|
||||
<value>yesterday</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,26 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ProjectsEditor.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.1.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
@@ -1,55 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019">
|
||||
|
||||
<Style
|
||||
x:Key="IconOnlyButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border
|
||||
x:Name="Background"
|
||||
Background="Transparent"
|
||||
CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}"
|
||||
SnapsToDevicePixels="True">
|
||||
<Border
|
||||
x:Name="Border"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}">
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Focusable="False"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="Background" Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />
|
||||
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPointerOver}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="Background" Property="Background" Value="{DynamicResource ButtonBackgroundPressed}" />
|
||||
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPressed}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="Background" Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" />
|
||||
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" />
|
||||
<Setter TargetName="ContentPresenter" Property="TextElement.Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -1,25 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">Dark.Accent1</system:String>
|
||||
<system:String x:Key="Theme.Origin">Origin</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent1 (Dark)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">Dark</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent1</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">Black</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF242424" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF2b2b2b" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FF373737" />
|
||||
<SolidColorBrush x:Key="MonitorViewBackgroundBrush" Color="#FF161616" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFFFFFFF" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="#FF373737" />
|
||||
<SolidColorBrush x:Key="SecondaryBorderBrush" Color="#FF494949" />
|
||||
<SolidColorBrush x:Key="TertiaryBorderBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#40F0F0F0" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
</ResourceDictionary>
|
||||
@@ -1,25 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">HighContrast.Accent2</system:String>
|
||||
<system:String x:Key="Theme.Origin">Origin</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent2 (HighContrast)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent2</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF242424" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF1c1c1c" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="MonitorViewBackgroundBrush" Color="#FF161616" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffff00" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF00ff00" />
|
||||
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="#FF373737" />
|
||||
<SolidColorBrush x:Key="SecondaryBorderBrush" Color="#FF494949" />
|
||||
<SolidColorBrush x:Key="TertiaryBorderBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#E55B5B5B" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
</ResourceDictionary>
|
||||
@@ -1,25 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">HighContrast.Accent3</system:String>
|
||||
<system:String x:Key="Theme.Origin">Origin</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent3 (HighContrast)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent3</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF242424" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF1c1c1c" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="MonitorViewBackgroundBrush" Color="#FF161616" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffff00" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FFc0c0c0" />
|
||||
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="#FF373737" />
|
||||
<SolidColorBrush x:Key="SecondaryBorderBrush" Color="#FF494949" />
|
||||
<SolidColorBrush x:Key="TertiaryBorderBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#E55B5B5B" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
</ResourceDictionary>
|
||||
@@ -1,25 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">HighContrast.Accent4</system:String>
|
||||
<system:String x:Key="Theme.Origin">Origin</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent4 (HighContrast)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent4</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF242424" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF1c1c1c" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="MonitorViewBackgroundBrush" Color="#FF161616" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffffff" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF1aebff" />
|
||||
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="#FF373737" />
|
||||
<SolidColorBrush x:Key="SecondaryBorderBrush" Color="#FF494949" />
|
||||
<SolidColorBrush x:Key="TertiaryBorderBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#E55B5B5B" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a" />
|
||||
</ResourceDictionary>
|
||||
@@ -1,25 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">HighContrast.Accent5</system:String>
|
||||
<system:String x:Key="Theme.Origin">Origin</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent5 (HighContrast)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent5</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFf9f9f9" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FFeeeeee" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FFF3F3F3" />
|
||||
<SolidColorBrush x:Key="MonitorViewBackgroundBrush" Color="#FF161616" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF000000" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF37006e" />
|
||||
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="#FF373737" />
|
||||
<SolidColorBrush x:Key="SecondaryBorderBrush" Color="#FF494949" />
|
||||
<SolidColorBrush x:Key="TertiaryBorderBrush" Color="#FF202020" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#E5949494" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF949494" />
|
||||
</ResourceDictionary>
|
||||
@@ -1,25 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<!-- Metadata -->
|
||||
<system:String x:Key="Theme.Name">Light.Accent1</system:String>
|
||||
<system:String x:Key="Theme.Origin">Origin</system:String>
|
||||
<system:String x:Key="Theme.DisplayName">Accent1 (Light)</system:String>
|
||||
<system:String x:Key="Theme.BaseColorScheme">Light</system:String>
|
||||
<system:String x:Key="Theme.ColorScheme">Accent1</system:String>
|
||||
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFf3f3f3" />
|
||||
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FFfbfbfb" />
|
||||
<SolidColorBrush x:Key="TertiaryBackgroundBrush" Color="#FFfefefe" />
|
||||
<SolidColorBrush x:Key="MonitorViewBackgroundBrush" Color="#FFF9F9F9" />
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF191919" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF6A6A6A" />
|
||||
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="#FFe5e5e5" />
|
||||
<SolidColorBrush x:Key="SecondaryBorderBrush" Color="#FFe5e5e5" />
|
||||
<SolidColorBrush x:Key="TertiaryBorderBrush" Color="#FFe5e5e5" />
|
||||
<SolidColorBrush x:Key="BackdropBrush" Color="#85F0F0F0" />
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF949494" />
|
||||
</ResourceDictionary>
|
||||
@@ -1,18 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ProjectsEditor.Utils
|
||||
{
|
||||
public class DashCaseNamingPolicy : JsonNamingPolicy
|
||||
{
|
||||
public static DashCaseNamingPolicy Instance { get; } = new DashCaseNamingPolicy();
|
||||
|
||||
public override string ConvertName(string name)
|
||||
{
|
||||
return name.UpperCamelCaseToDashCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,347 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Media.Imaging;
|
||||
using ManagedCommon;
|
||||
using ProjectsEditor.Models;
|
||||
|
||||
namespace ProjectsEditor.Utils
|
||||
{
|
||||
public class DrawHelper
|
||||
{
|
||||
private static Font font = new("Tahoma", 24);
|
||||
|
||||
public static BitmapImage DrawPreview(Project project, Rectangle bounds)
|
||||
{
|
||||
List<double> horizontalGaps = new List<double>();
|
||||
List<double> verticalGaps = new List<double>();
|
||||
double gapWidth = bounds.Width * 0.01;
|
||||
double gapHeight = bounds.Height * 0.01;
|
||||
|
||||
double scale = 0.1;
|
||||
int Scaled(double value)
|
||||
{
|
||||
return (int)(value * scale);
|
||||
}
|
||||
|
||||
int TransformX(double posX)
|
||||
{
|
||||
double gapTransform = verticalGaps.Where(x => x <= posX).Count() * gapWidth;
|
||||
return Scaled(posX - bounds.Left + gapTransform);
|
||||
}
|
||||
|
||||
int TransformY(double posY)
|
||||
{
|
||||
double gapTransform = horizontalGaps.Where(x => x <= posY).Count() * gapHeight;
|
||||
return Scaled(posY - bounds.Top + gapTransform);
|
||||
}
|
||||
|
||||
Dictionary<string, int> repeatCounter = new Dictionary<string, int>();
|
||||
|
||||
var selectedApps = project.Applications.Where(x => x.IsSelected);
|
||||
foreach (Application app in selectedApps)
|
||||
{
|
||||
if (repeatCounter.TryGetValue(app.AppPath, out int value))
|
||||
{
|
||||
repeatCounter[app.AppPath] = ++value;
|
||||
}
|
||||
else
|
||||
{
|
||||
repeatCounter.Add(app.AppPath, 1);
|
||||
}
|
||||
|
||||
app.RepeatIndex = repeatCounter[app.AppPath];
|
||||
}
|
||||
|
||||
// remove those repeatIndexes, which are single 1-es (no repetitions) by setting them to 0
|
||||
foreach (Application app in selectedApps.Where(x => repeatCounter[x.AppPath] == 1))
|
||||
{
|
||||
app.RepeatIndex = 0;
|
||||
}
|
||||
|
||||
foreach (Application app in project.Applications.Where(x => !x.IsSelected))
|
||||
{
|
||||
app.RepeatIndex = 0;
|
||||
}
|
||||
|
||||
// now that all repeat index values are set, update the repeat index strings on UI
|
||||
foreach (Application app in project.Applications)
|
||||
{
|
||||
app.OnPropertyChanged(new PropertyChangedEventArgs("RepeatIndexString"));
|
||||
}
|
||||
|
||||
foreach (MonitorSetup monitor in project.Monitors)
|
||||
{
|
||||
// check for vertical gap
|
||||
if (monitor.MonitorDpiAwareBounds.Left > bounds.Left && project.Monitors.Any(x => x.MonitorDpiAwareBounds.Right <= monitor.MonitorDpiAwareBounds.Left))
|
||||
{
|
||||
verticalGaps.Add(monitor.MonitorDpiAwareBounds.Left);
|
||||
}
|
||||
|
||||
// check for horizontal gap
|
||||
if (monitor.MonitorDpiAwareBounds.Top > bounds.Top && project.Monitors.Any(x => x.MonitorDpiAwareBounds.Bottom <= monitor.MonitorDpiAwareBounds.Top))
|
||||
{
|
||||
horizontalGaps.Add(monitor.MonitorDpiAwareBounds.Top);
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap previewBitmap = new Bitmap(Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled((bounds.Height * 1.2) + (horizontalGaps.Count * gapHeight)));
|
||||
double desiredIconSize = Scaled(Math.Min(bounds.Width, bounds.Height)) * 0.3;
|
||||
using (Graphics g = Graphics.FromImage(previewBitmap))
|
||||
{
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
Brush brush = new SolidBrush(Common.ThemeManager.GetCurrentTheme() == Common.Theme.Dark ? Color.FromArgb(10, 255, 255, 255) : Color.FromArgb(10, 0, 0, 0));
|
||||
|
||||
// draw the monitors
|
||||
foreach (MonitorSetup monitor in project.Monitors)
|
||||
{
|
||||
Brush monitorBrush = new SolidBrush(Common.ThemeManager.GetCurrentTheme() == Common.Theme.Dark ? Color.FromArgb(32, 7, 91, 155) : Color.FromArgb(32, 7, 91, 155));
|
||||
g.FillRectangle(monitorBrush, new Rectangle(TransformX(monitor.MonitorDpiAwareBounds.Left), TransformY(monitor.MonitorDpiAwareBounds.Top), Scaled(monitor.MonitorDpiAwareBounds.Width), Scaled(monitor.MonitorDpiAwareBounds.Height)));
|
||||
}
|
||||
|
||||
var appsToDraw = project.Applications.Where(x => x.IsSelected && !x.Minimized);
|
||||
|
||||
// draw the highlighted app at the end to have its icon in the foreground for the case there are overlapping icons
|
||||
foreach (Application app in appsToDraw.Where(x => !x.IsHighlighted))
|
||||
{
|
||||
Rectangle rect = new Rectangle(TransformX(app.ScaledPosition.X), TransformY(app.ScaledPosition.Y), Scaled(app.ScaledPosition.Width), Scaled(app.ScaledPosition.Height));
|
||||
DrawWindow(g, brush, rect, app, desiredIconSize);
|
||||
}
|
||||
|
||||
foreach (Application app in appsToDraw.Where(x => x.IsHighlighted))
|
||||
{
|
||||
Rectangle rect = new Rectangle(TransformX(app.ScaledPosition.X), TransformY(app.ScaledPosition.Y), Scaled(app.ScaledPosition.Width), Scaled(app.ScaledPosition.Height));
|
||||
DrawWindow(g, brush, rect, app, desiredIconSize);
|
||||
}
|
||||
|
||||
// draw the minimized windows
|
||||
Rectangle rectMinimized = new Rectangle(0, Scaled((bounds.Height * 1.02) + (horizontalGaps.Count * gapHeight)), Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled(bounds.Height * 0.18));
|
||||
DrawWindow(g, brush, rectMinimized, project.Applications.Where(x => x.IsSelected && x.Minimized));
|
||||
}
|
||||
|
||||
using (var memory = new MemoryStream())
|
||||
{
|
||||
previewBitmap.Save(memory, ImageFormat.Png);
|
||||
memory.Position = 0;
|
||||
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.StreamSource = memory;
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapImage.EndInit();
|
||||
bitmapImage.Freeze();
|
||||
|
||||
return bitmapImage;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawWindow(Graphics graphics, Brush brush, Rectangle bounds, Application app, double desiredIconSize)
|
||||
{
|
||||
if (graphics == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (brush == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (GraphicsPath path = RoundedRect(bounds))
|
||||
{
|
||||
if (app.IsHighlighted)
|
||||
{
|
||||
graphics.DrawPath(new Pen(Common.ThemeManager.GetCurrentTheme() == Common.Theme.Dark ? Color.White : Color.DarkGray, graphics.VisibleClipBounds.Height / 50), path);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.DrawPath(new Pen(Common.ThemeManager.GetCurrentTheme() == Common.Theme.Dark ? Color.FromArgb(128, 82, 82, 82) : Color.FromArgb(128, 160, 160, 160), graphics.VisibleClipBounds.Height / 200), path);
|
||||
}
|
||||
|
||||
graphics.FillPath(brush, path);
|
||||
}
|
||||
|
||||
double iconSize = Math.Min(Math.Min(bounds.Width - 4, bounds.Height - 4), desiredIconSize);
|
||||
Rectangle iconBounds = new Rectangle((int)(bounds.Left + (bounds.Width / 2) - (iconSize / 2)), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize);
|
||||
|
||||
try
|
||||
{
|
||||
graphics.DrawIcon(app.Icon, iconBounds);
|
||||
if (app.RepeatIndex > 0)
|
||||
{
|
||||
string indexString = app.RepeatIndex.ToString(CultureInfo.InvariantCulture);
|
||||
int indexSize = (int)(iconBounds.Width * 0.5);
|
||||
Rectangle indexBounds = new Rectangle(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize);
|
||||
|
||||
var textSize = graphics.MeasureString(indexString, font);
|
||||
var state = graphics.Save();
|
||||
graphics.TranslateTransform(indexBounds.Left, indexBounds.Top);
|
||||
graphics.ScaleTransform(indexBounds.Width / textSize.Width, indexBounds.Height / textSize.Height);
|
||||
graphics.DrawString(indexString, font, Brushes.Black, PointF.Empty);
|
||||
graphics.Restore(state);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// sometimes drawing an icon throws an exception despite that the icon seems to be ok
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawWindow(Graphics graphics, Brush brush, Rectangle bounds, IEnumerable<Application> apps)
|
||||
{
|
||||
int appsCount = apps.Count();
|
||||
if (appsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (graphics == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (brush == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (GraphicsPath path = RoundedRect(bounds))
|
||||
{
|
||||
if (apps.Where(x => x.IsHighlighted).Any())
|
||||
{
|
||||
graphics.DrawPath(new Pen(Common.ThemeManager.GetCurrentTheme() == Common.Theme.Dark ? Color.White : Color.DarkGray, graphics.VisibleClipBounds.Height / 50), path);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.DrawPath(new Pen(Common.ThemeManager.GetCurrentTheme() == Common.Theme.Dark ? Color.FromArgb(128, 82, 82, 82) : Color.FromArgb(128, 160, 160, 160), graphics.VisibleClipBounds.Height / 200), path);
|
||||
}
|
||||
|
||||
graphics.FillPath(brush, path);
|
||||
}
|
||||
|
||||
double iconSize = Math.Min(bounds.Width, bounds.Height) * 0.5;
|
||||
for (int iconCounter = 0; iconCounter < appsCount; iconCounter++)
|
||||
{
|
||||
Application app = apps.ElementAt(iconCounter);
|
||||
Rectangle iconBounds = new Rectangle((int)(bounds.Left + (bounds.Width / 2) - (iconSize * ((appsCount / 2) - iconCounter))), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize);
|
||||
|
||||
try
|
||||
{
|
||||
graphics.DrawIcon(app.Icon, iconBounds);
|
||||
if (app.RepeatIndex > 0)
|
||||
{
|
||||
string indexString = app.RepeatIndex.ToString(CultureInfo.InvariantCulture);
|
||||
int indexSize = (int)(iconBounds.Width * 0.5);
|
||||
Rectangle indexBounds = new Rectangle(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize);
|
||||
|
||||
var textSize = graphics.MeasureString(indexString, font);
|
||||
var state = graphics.Save();
|
||||
graphics.TranslateTransform(indexBounds.Left, indexBounds.Top);
|
||||
graphics.ScaleTransform(indexBounds.Width / textSize.Width, indexBounds.Height / textSize.Height);
|
||||
graphics.DrawString(indexString, font, Brushes.Black, PointF.Empty);
|
||||
graphics.Restore(state);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// sometimes drawing an icon throws an exception despite that the icon seems to be ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static BitmapImage DrawPreviewIcons(Project project)
|
||||
{
|
||||
var selectedApps = project.Applications.Where(x => x.IsSelected);
|
||||
int appsCount = selectedApps.Count();
|
||||
if (appsCount == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Bitmap previewBitmap = new Bitmap(32 * appsCount, 24);
|
||||
using (Graphics graphics = Graphics.FromImage(previewBitmap))
|
||||
{
|
||||
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
int appIndex = 0;
|
||||
foreach (var app in selectedApps)
|
||||
{
|
||||
try
|
||||
{
|
||||
graphics.DrawIcon(app.Icon, new Rectangle(32 * appIndex, 0, 24, 24));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception while drawing the icon for app {app.AppName}. Exception message: {e.Message}");
|
||||
}
|
||||
|
||||
appIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
using (var memory = new MemoryStream())
|
||||
{
|
||||
previewBitmap.Save(memory, ImageFormat.Png);
|
||||
memory.Position = 0;
|
||||
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.StreamSource = memory;
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapImage.EndInit();
|
||||
bitmapImage.Freeze();
|
||||
|
||||
return bitmapImage;
|
||||
}
|
||||
}
|
||||
|
||||
private static GraphicsPath RoundedRect(Rectangle bounds)
|
||||
{
|
||||
int minorSize = Math.Min(bounds.Width, bounds.Height);
|
||||
int radius = (int)(minorSize / 8);
|
||||
|
||||
int diameter = radius * 2;
|
||||
Size size = new Size(diameter, diameter);
|
||||
Rectangle arc = new Rectangle(bounds.Location, size);
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
|
||||
if (radius == 0)
|
||||
{
|
||||
path.AddRectangle(bounds);
|
||||
return path;
|
||||
}
|
||||
|
||||
// top left arc
|
||||
path.AddArc(arc, 180, 90);
|
||||
|
||||
// top right arc
|
||||
arc.X = bounds.Right - diameter;
|
||||
path.AddArc(arc, 270, 90);
|
||||
|
||||
// bottom right arc
|
||||
arc.Y = bounds.Bottom - diameter;
|
||||
path.AddArc(arc, 0, 90);
|
||||
|
||||
// bottom left arc
|
||||
arc.X = bounds.Left;
|
||||
path.AddArc(arc, 90, 90);
|
||||
|
||||
path.CloseFigure();
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace ProjectsEditor.Utils
|
||||
{
|
||||
public class FolderUtils
|
||||
{
|
||||
public static string Desktop()
|
||||
{
|
||||
return Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
}
|
||||
|
||||
public static string Temp()
|
||||
{
|
||||
return Path.GetTempPath();
|
||||
}
|
||||
|
||||
// Note: the same path should be used in SnapshotTool and Launcher
|
||||
public static string DataFolder()
|
||||
{
|
||||
return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Microsoft\\PowerToys\\Projects";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ProjectsEditor.Utils
|
||||
{
|
||||
public class IOUtils
|
||||
{
|
||||
private readonly IFileSystem _fileSystem = new FileSystem();
|
||||
|
||||
public IOUtils()
|
||||
{
|
||||
}
|
||||
|
||||
public void WriteFile(string fileName, string data)
|
||||
{
|
||||
_fileSystem.File.WriteAllText(fileName, data);
|
||||
}
|
||||
|
||||
public string ReadFile(string fileName)
|
||||
{
|
||||
if (_fileSystem.File.Exists(fileName))
|
||||
{
|
||||
var attempts = 0;
|
||||
while (attempts < 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Stream inputStream = _fileSystem.File.Open(fileName, FileMode.Open))
|
||||
using (StreamReader reader = new StreamReader(inputStream))
|
||||
{
|
||||
string data = reader.ReadToEnd();
|
||||
inputStream.Close();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Task.Delay(10).Wait();
|
||||
}
|
||||
|
||||
attempts++;
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ProjectsEditor.Utils
|
||||
{
|
||||
internal sealed class NativeMethods
|
||||
{
|
||||
public const int SW_RESTORE = 9;
|
||||
public const int SW_NORMAL = 1;
|
||||
public const int SW_MINIMIZE = 6;
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
|
||||
|
||||
[DllImport("USER32.DLL")]
|
||||
public static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetForegroundWindow();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint GetCurrentThreadId();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user