Merge branch 'dev/feature/projects' of https://github.com/microsoft/PowerToys into dev/feature/projects

This commit is contained in:
seraphima
2024-06-10 14:19:34 +02:00
7 changed files with 118 additions and 60 deletions

View File

@@ -51,6 +51,26 @@ namespace ProjectsEditor.Models
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; }
@@ -85,9 +105,17 @@ namespace ProjectsEditor.Models
{
Task<AppListEntry> task = Task.Run<AppListEntry>(async () => await GetAppByPackageFamilyNameAsync());
AppListEntry packApp = task.Result;
string filename = Path.GetFileName(AppPath);
string newExeLocation = Path.Combine(packApp.AppInfo.Package.InstalledPath, filename);
_icon = Icon.ExtractAssociatedIcon(newExeLocation);
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
{
@@ -97,6 +125,7 @@ namespace ProjectsEditor.Models
catch (Exception e)
{
Logger.LogError($"Exception while extracting icon from app path: {AppPath}. Exception message: {e.Message}");
IsNotFound = true;
_icon = new Icon(@"images\DefaultIcon.ico");
}
}

View File

@@ -213,6 +213,7 @@ namespace ProjectsEditor.Models
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,
});
@@ -246,7 +247,7 @@ namespace ProjectsEditor.Models
public async void Initialize()
{
PreviewImage = await Task.Run(() => DrawPreviewIcons());
PreviewImage = await Task.Run(() => DrawHelper.DrawPreviewIcons(this));
foreach (MonitorSetup monitor in Monitors)
{
System.Windows.Rect rect = monitor.MonitorDpiAwareBounds;
@@ -254,53 +255,6 @@ namespace ProjectsEditor.Models
}
}
private BitmapImage DrawPreviewIcons()
{
var selectedApps = 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 {Name}. 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 Rectangle GetCommonBounds()
{
double minX = Monitors.First().MonitorDpiUnawareBounds.Left;

View File

@@ -10,6 +10,8 @@
Title="Project Editor"
Background="{DynamicResource PrimaryBackgroundBrush}">
<Page.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<DataTemplate x:Key="headerTemplate">
<Border>
<TextBlock
@@ -28,13 +30,25 @@
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="&#xE945;"
Foreground="Red"
FontSize="14"
FontFamily="{DynamicResource SymbolThemeFontFamily}"
FontWeight="Normal"
Margin="2 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"
@@ -42,7 +56,7 @@
Margin="10"
Source="{Binding IconBitmapImage}"/>
<TextBlock
Grid.Column="1"
Grid.Column="2"
Text="{Binding RepeatIndexString, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Foreground="{DynamicResource PrimaryForegroundBrush}"
FontSize="14"
@@ -50,7 +64,7 @@
Width="20"
VerticalAlignment="Center"/>
<TextBlock
Grid.Column="2"
Grid.Column="3"
Text="{Binding AppName}"
Foreground="{DynamicResource PrimaryForegroundBrush}"
FontSize="14"
@@ -58,7 +72,7 @@
VerticalAlignment="Center"/>
<TextBox
x:Name="CommandLineTextBox"
Grid.Column="3"
Grid.Column="4"
Text="{Binding CommandLineArguments, Mode=TwoWay}"
Foreground="{DynamicResource PrimaryForegroundBrush}"
Background="{DynamicResource TertiaryBackgroundBrush}"
@@ -67,7 +81,7 @@
FontWeight="Normal"
VerticalContentAlignment="Center" />
<TextBlock
Grid.Column="3"
Grid.Column="4"
IsHitTestVisible="False"
Text="{x:Static props:Resources.WriteArgs}"
Foreground="{DynamicResource SecondaryForegroundBrush}"
@@ -88,7 +102,7 @@
</TextBlock.Style>
</TextBlock>
<CheckBox
Grid.Column="4"
Grid.Column="5"
IsChecked="{Binding IsSelected, Mode=TwoWay}"
Checked="CheckBox_Checked"
Unchecked="CheckBox_Checked"

View File

@@ -285,6 +285,15 @@ namespace ProjectsEditor.Properties {
}
}
/// <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>

View File

@@ -189,6 +189,9 @@
<data name="New_project" xml:space="preserve">
<value>New project</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>

View File

@@ -12,6 +12,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows.Media.Imaging;
using ManagedCommon;
using ProjectsEditor.Models;
namespace ProjectsEditor.Utils
@@ -140,11 +141,11 @@ namespace ProjectsEditor.Utils
{
if (app.IsHighlighted)
{
graphics.DrawPath(new Pen(Common.ThemeManager.GetCurrentTheme() == Common.Theme.Dark ? Color.White : Color.DarkGray, graphics.VisibleClipBounds.Height / 25), path);
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 / 100), path);
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);
@@ -198,11 +199,11 @@ namespace ProjectsEditor.Utils
{
if (apps.Where(x => x.IsHighlighted).Any())
{
graphics.DrawPath(new Pen(Common.ThemeManager.GetCurrentTheme() == Common.Theme.Dark ? Color.White : Color.DarkGray, graphics.VisibleClipBounds.Height / 25), path);
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 / 100), path);
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);
@@ -395,6 +396,53 @@ namespace ProjectsEditor.Utils
return shortcutIconFilename;
}
internal 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 void CreateExamples(Project project)
{
Bitmap bitmap = new Bitmap(IconSize + 1000, IconSize * iconBrushes.Count);

View File

@@ -118,6 +118,7 @@ namespace ProjectsEditor.Utils
Maximized = app.Maximized,
Minimized = app.Minimized,
IsSelected = true,
IsNotFound = false,
Position = new Models.Application.WindowPosition()
{
Height = app.Position.Height,