mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
[Projects] Add Select all checkbox, Delete selected button
This commit is contained in:
@@ -71,8 +71,21 @@ namespace ProjectsEditor.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _isSelected;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public bool IsSelected { get; set; }
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get => _isSelected;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_isSelected != value)
|
||||||
|
{
|
||||||
|
_isSelected = value;
|
||||||
|
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsSelected)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public bool IsHighlighted { get; set; }
|
public bool IsHighlighted { get; set; }
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ namespace ProjectsEditor.Models
|
|||||||
|
|
||||||
public bool CanBeSaved
|
public bool CanBeSaved
|
||||||
{
|
{
|
||||||
get => Name.Length > 0 && Applications.Where(x => x.IsSelected).Any();
|
get => Name.Length > 0 && Applications.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _isPopupVisible;
|
private bool _isPopupVisible;
|
||||||
@@ -177,11 +177,13 @@ namespace ProjectsEditor.Models
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
int count = Applications.Where(x => x.IsSelected).Count();
|
int count = Applications.Count;
|
||||||
return count.ToString(CultureInfo.InvariantCulture) + " " + (count == 1 ? Properties.Resources.App : Properties.Resources.Apps);
|
return count.ToString(CultureInfo.InvariantCulture) + " " + (count == 1 ? Properties.Resources.App : Properties.Resources.Apps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsAnySelected { get => Applications?.Any(x => x.IsSelected) == true; }
|
||||||
|
|
||||||
public List<MonitorSetup> Monitors { get; set; }
|
public List<MonitorSetup> Monitors { get; set; }
|
||||||
|
|
||||||
private BitmapImage _previewIcons;
|
private BitmapImage _previewIcons;
|
||||||
@@ -216,7 +218,7 @@ namespace ProjectsEditor.Models
|
|||||||
PackageFullName = item.PackageFullName,
|
PackageFullName = item.PackageFullName,
|
||||||
Minimized = item.Minimized,
|
Minimized = item.Minimized,
|
||||||
Maximized = item.Maximized,
|
Maximized = item.Maximized,
|
||||||
IsSelected = item.IsSelected,
|
IsSelected = false,
|
||||||
MonitorNumber = item.MonitorNumber,
|
MonitorNumber = item.MonitorNumber,
|
||||||
IsNotFound = item.IsNotFound,
|
IsNotFound = item.IsNotFound,
|
||||||
Position = new Application.WindowPosition() { X = item.Position.X, Y = item.Position.Y, Height = item.Position.Height, Width = item.Position.Width },
|
Position = new Application.WindowPosition() { X = item.Position.X, Y = item.Position.Y, Height = item.Position.Height, Width = item.Position.Width },
|
||||||
|
|||||||
@@ -103,7 +103,7 @@
|
|||||||
</TextBlock>
|
</TextBlock>
|
||||||
<CheckBox
|
<CheckBox
|
||||||
Grid.Column="5"
|
Grid.Column="5"
|
||||||
IsChecked="{Binding IsSelected, Mode=TwoWay}"
|
IsChecked="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
Checked="CheckBox_Checked"
|
Checked="CheckBox_Checked"
|
||||||
Unchecked="CheckBox_Checked"
|
Unchecked="CheckBox_Checked"
|
||||||
Margin="10"/>
|
Margin="10"/>
|
||||||
@@ -151,7 +151,26 @@
|
|||||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||||
VerticalAlignment="Center"/>
|
VerticalAlignment="Center"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Row="1" Orientation="Vertical">
|
<DockPanel Grid.Row="1">
|
||||||
|
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" >
|
||||||
|
<Button x:Name="DeleteButton"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Height="36"
|
||||||
|
Padding="24,0,24,0"
|
||||||
|
Content="{x:Static props:Resources.DeleteSelected}"
|
||||||
|
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||||
|
AutomationProperties.Name="{x:Static props:Resources.Cancel}"
|
||||||
|
IsEnabled="{Binding IsAnySelected, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Click="RemoveSelectedButtonClicked"/>
|
||||||
|
<CheckBox
|
||||||
|
x:Name="SelectAllCheckBox"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
FontSize="14"
|
||||||
|
Content="{x:Static props:Resources.SelectedAllInProject}"
|
||||||
|
Checked="SelectAllCheckBox_Modified"
|
||||||
|
Unchecked="SelectAllCheckBox_Modified"/>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel DockPanel.Dock="Left" Orientation="Vertical">
|
||||||
<TextBlock Text="{x:Static props:Resources.ProjectName}" FontSize="14" FontWeight="Normal" Foreground="{DynamicResource PrimaryForegroundBrush}"/>
|
<TextBlock Text="{x:Static props:Resources.ProjectName}" FontSize="14" FontWeight="Normal" Foreground="{DynamicResource PrimaryForegroundBrush}"/>
|
||||||
<TextBox
|
<TextBox
|
||||||
x:Name="EditNameTextBox"
|
x:Name="EditNameTextBox"
|
||||||
@@ -166,6 +185,7 @@
|
|||||||
TextChanged="EditNameTextBox_TextChanged"
|
TextChanged="EditNameTextBox_TextChanged"
|
||||||
KeyDown="EditNameTextBoxKeyDown" />
|
KeyDown="EditNameTextBoxKeyDown" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</DockPanel>
|
||||||
<Border
|
<Border
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
@@ -189,7 +209,7 @@
|
|||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<ItemsControl
|
<ItemsControl
|
||||||
ItemsSource="{Binding ApplicationsListed, Mode=OneWay}"
|
ItemsSource="{Binding ApplicationsListed, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
ItemTemplateSelector="{StaticResource AppListDataTemplateSelector}">
|
ItemTemplateSelector="{StaticResource AppListDataTemplateSelector}">
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace ProjectsEditor
|
|||||||
Models.Application application = checkBox.DataContext as Models.Application;
|
Models.Application application = checkBox.DataContext as Models.Application;
|
||||||
Models.Project project = application.Parent;
|
Models.Project project = application.Parent;
|
||||||
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.CanBeSaved)));
|
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.CanBeSaved)));
|
||||||
|
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.IsAnySelected)));
|
||||||
project.Initialize();
|
project.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +41,12 @@ namespace ProjectsEditor
|
|||||||
_mainViewModel.SwitchToMainView();
|
_mainViewModel.SwitchToMainView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RemoveSelectedButtonClicked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Project projectToSave = this.DataContext as Project;
|
||||||
|
_mainViewModel.RemoveSelectedApps(projectToSave);
|
||||||
|
}
|
||||||
|
|
||||||
private void CancelButtonClicked(object sender, RoutedEventArgs e)
|
private void CancelButtonClicked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_mainViewModel.CancelLastEdit();
|
_mainViewModel.CancelLastEdit();
|
||||||
@@ -91,5 +98,12 @@ namespace ProjectsEditor
|
|||||||
project.Name = EditNameTextBox.Text;
|
project.Name = EditNameTextBox.Text;
|
||||||
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.CanBeSaved)));
|
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.CanBeSaved)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SelectAllCheckBox_Modified(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Project project = this.DataContext as Project;
|
||||||
|
bool newValue = SelectAllCheckBox.IsChecked == true;
|
||||||
|
_mainViewModel.UpdateIsSelectedStates(project, newValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,6 +168,15 @@ namespace ProjectsEditor.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Remove Selected Apps.
|
||||||
|
/// </summary>
|
||||||
|
public static string DeleteSelected {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeleteSelected", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Edit.
|
/// Looks up a localized string similar to Edit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -438,6 +447,15 @@ namespace ProjectsEditor.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Select All Apps in Project.
|
||||||
|
/// </summary>
|
||||||
|
public static string SelectedAllInProject {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SelectedAllInProject", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Sort by.
|
/// Looks up a localized string similar to Sort by.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -150,6 +150,9 @@
|
|||||||
<data name="Delete" xml:space="preserve">
|
<data name="Delete" xml:space="preserve">
|
||||||
<value>Remove</value>
|
<value>Remove</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DeleteSelected" xml:space="preserve">
|
||||||
|
<value>Remove Selected Apps</value>
|
||||||
|
</data>
|
||||||
<data name="Delete_Project_Dialog_Announce" xml:space="preserve">
|
<data name="Delete_Project_Dialog_Announce" xml:space="preserve">
|
||||||
<value>Delete project dialog.</value>
|
<value>Delete project dialog.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -243,6 +246,9 @@
|
|||||||
<data name="SecondsAgo" xml:space="preserve">
|
<data name="SecondsAgo" xml:space="preserve">
|
||||||
<value>seconds ago</value>
|
<value>seconds ago</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SelectedAllInProject" xml:space="preserve">
|
||||||
|
<value>Select All Apps in Project</value>
|
||||||
|
</data>
|
||||||
<data name="SortBy" xml:space="preserve">
|
<data name="SortBy" xml:space="preserve">
|
||||||
<value>Sort by</value>
|
<value>Sort by</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -48,8 +48,7 @@ namespace ProjectsEditor.Utils
|
|||||||
|
|
||||||
Dictionary<string, int> repeatCounter = new Dictionary<string, int>();
|
Dictionary<string, int> repeatCounter = new Dictionary<string, int>();
|
||||||
|
|
||||||
var selectedApps = project.Applications.Where(x => x.IsSelected);
|
foreach (Application app in project.Applications)
|
||||||
foreach (Application app in selectedApps)
|
|
||||||
{
|
{
|
||||||
if (repeatCounter.TryGetValue(app.AppPath, out int value))
|
if (repeatCounter.TryGetValue(app.AppPath, out int value))
|
||||||
{
|
{
|
||||||
@@ -64,12 +63,12 @@ namespace ProjectsEditor.Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove those repeatIndexes, which are single 1-es (no repetitions) by setting them to 0
|
// 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))
|
foreach (Application app in project.Applications.Where(x => repeatCounter[x.AppPath] == 1))
|
||||||
{
|
{
|
||||||
app.RepeatIndex = 0;
|
app.RepeatIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Application app in project.Applications.Where(x => !x.IsSelected))
|
foreach (Application app in project.Applications)
|
||||||
{
|
{
|
||||||
app.RepeatIndex = 0;
|
app.RepeatIndex = 0;
|
||||||
}
|
}
|
||||||
@@ -112,7 +111,7 @@ namespace ProjectsEditor.Utils
|
|||||||
g.FillRectangle(monitorBrush, new Rectangle(TransformX(monitor.MonitorDpiAwareBounds.Left), TransformY(monitor.MonitorDpiAwareBounds.Top), Scaled(monitor.MonitorDpiAwareBounds.Width), Scaled(monitor.MonitorDpiAwareBounds.Height)));
|
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);
|
var appsToDraw = project.Applications.Where(x => !x.Minimized);
|
||||||
|
|
||||||
// draw the highlighted app at the end to have its icon in the foreground for the case there are overlapping icons
|
// 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))
|
foreach (Application app in appsToDraw.Where(x => !x.IsHighlighted))
|
||||||
@@ -129,7 +128,7 @@ namespace ProjectsEditor.Utils
|
|||||||
|
|
||||||
// draw the minimized windows
|
// 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));
|
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));
|
DrawWindow(g, brush, rectMinimized, project.Applications.Where(x => x.Minimized));
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var memory = new MemoryStream())
|
using (var memory = new MemoryStream())
|
||||||
@@ -264,8 +263,7 @@ namespace ProjectsEditor.Utils
|
|||||||
|
|
||||||
public static BitmapImage DrawPreviewIcons(Project project)
|
public static BitmapImage DrawPreviewIcons(Project project)
|
||||||
{
|
{
|
||||||
var selectedApps = project.Applications.Where(x => x.IsSelected);
|
int appsCount = project.Applications.Count;
|
||||||
int appsCount = selectedApps.Count();
|
|
||||||
if (appsCount == 0)
|
if (appsCount == 0)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -278,7 +276,7 @@ namespace ProjectsEditor.Utils
|
|||||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
int appIndex = 0;
|
int appIndex = 0;
|
||||||
foreach (var app in selectedApps)
|
foreach (var app in project.Applications)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ namespace ProjectsEditor.Utils
|
|||||||
CommandLineArguments = app.CommandLineArguments,
|
CommandLineArguments = app.CommandLineArguments,
|
||||||
Maximized = app.Maximized,
|
Maximized = app.Maximized,
|
||||||
Minimized = app.Minimized,
|
Minimized = app.Minimized,
|
||||||
IsSelected = true,
|
IsSelected = false,
|
||||||
IsNotFound = false,
|
IsNotFound = false,
|
||||||
Position = new Models.Application.WindowPosition()
|
Position = new Models.Application.WindowPosition()
|
||||||
{
|
{
|
||||||
@@ -160,8 +160,6 @@ namespace ProjectsEditor.Utils
|
|||||||
};
|
};
|
||||||
|
|
||||||
foreach (var app in project.Applications)
|
foreach (var app in project.Applications)
|
||||||
{
|
|
||||||
if (app.IsSelected)
|
|
||||||
{
|
{
|
||||||
wrapper.Applications.Add(new ProjectsData.ApplicationWrapper
|
wrapper.Applications.Add(new ProjectsData.ApplicationWrapper
|
||||||
{
|
{
|
||||||
@@ -182,7 +180,6 @@ namespace ProjectsEditor.Utils
|
|||||||
Monitor = app.MonitorNumber,
|
Monitor = app.MonitorNumber,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var monitor in project.Monitors)
|
foreach (var monitor in project.Monitors)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ namespace ProjectsEditor.ViewModels
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return x.Applications.Any(app => app.IsSelected && app.AppName.Contains(_searchTerm, StringComparison.InvariantCultureIgnoreCase));
|
return x.Applications.Any(app => app.AppName.Contains(_searchTerm, StringComparison.InvariantCultureIgnoreCase));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,18 +159,7 @@ namespace ProjectsEditor.ViewModels
|
|||||||
editedProject.IsShortcutNeeded = projectToSave.IsShortcutNeeded;
|
editedProject.IsShortcutNeeded = projectToSave.IsShortcutNeeded;
|
||||||
editedProject.PreviewIcons = projectToSave.PreviewIcons;
|
editedProject.PreviewIcons = projectToSave.PreviewIcons;
|
||||||
editedProject.PreviewImage = projectToSave.PreviewImage;
|
editedProject.PreviewImage = projectToSave.PreviewImage;
|
||||||
for (int appIndex = editedProject.Applications.Count - 1; appIndex >= 0; appIndex--)
|
editedProject.Applications = projectToSave.Applications;
|
||||||
{
|
|
||||||
if (!projectToSave.Applications[appIndex].IsSelected)
|
|
||||||
{
|
|
||||||
editedProject.Applications.RemoveAt(appIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
editedProject.Applications[appIndex].IsSelected = true;
|
|
||||||
editedProject.Applications[appIndex].CommandLineArguments = projectToSave.Applications[appIndex].CommandLineArguments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
editedProject.OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs("AppsCountString"));
|
editedProject.OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs("AppsCountString"));
|
||||||
editedProject.Initialize();
|
editedProject.Initialize();
|
||||||
@@ -360,5 +349,23 @@ namespace ProjectsEditor.ViewModels
|
|||||||
project.IsPopupVisible = false;
|
project.IsPopupVisible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void UpdateIsSelectedStates(Project project, bool newValue)
|
||||||
|
{
|
||||||
|
foreach (Application app in project.Applications)
|
||||||
|
{
|
||||||
|
app.IsSelected = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.IsAnySelected)));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RemoveSelectedApps(Project project)
|
||||||
|
{
|
||||||
|
project.Applications.RemoveAll(app => app.IsSelected);
|
||||||
|
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.ApplicationsListed)));
|
||||||
|
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.IsAnySelected)));
|
||||||
|
project.OnPropertyChanged(new PropertyChangedEventArgs(nameof(Project.CanBeSaved)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user