[Projects] Re-implementing preview drawing - one common image

This commit is contained in:
donlaci
2024-06-24 09:34:47 +02:00
parent 65e75d1c42
commit 371a05ac5e
6 changed files with 88 additions and 72 deletions

View File

@@ -210,7 +210,7 @@
VerticalAlignment="Center"
Margin="0,0,0,8" >
<Image
Source="{Binding PreviewImage, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Source="{Binding PreviewIcons, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Height="20" />
<TextBlock
Text="{Binding AppsCountString}"

View File

@@ -10,22 +10,6 @@ namespace ProjectsEditor.Models
{
public class MonitorSetup : Monitor, INotifyPropertyChanged
{
private BitmapImage _previewImage;
public BitmapImage PreviewImage
{
get
{
return _previewImage;
}
set
{
_previewImage = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(PreviewImage)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)

View File

@@ -184,11 +184,14 @@ namespace ProjectsEditor.Models
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;
@@ -197,7 +200,7 @@ namespace ProjectsEditor.Models
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) { PreviewImage = item.PreviewImage });
Monitors.Add(new MonitorSetup($"Screen {screenIndex}", item.MonitorInstanceId, item.MonitorNumber, item.Dpi, item.MonitorDpiAwareBounds, item.MonitorDpiUnawareBounds));
screenIndex++;
}
@@ -226,6 +229,20 @@ namespace ProjectsEditor.Models
{
}
public BitmapImage PreviewIcons
{
get
{
return _previewIcons;
}
set
{
_previewIcons = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(PreviewIcons)));
}
}
public BitmapImage PreviewImage
{
get
@@ -240,6 +257,20 @@ namespace ProjectsEditor.Models
}
}
public double PreviewImageWidth
{
get
{
return _previewImageWidth;
}
set
{
_previewImageWidth = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(PreviewImageWidth)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
@@ -249,12 +280,10 @@ namespace ProjectsEditor.Models
public async void Initialize()
{
PreviewImage = await Task.Run(() => DrawHelper.DrawPreviewIcons(this));
foreach (MonitorSetup monitor in Monitors)
{
System.Windows.Rect rect = monitor.MonitorDpiAwareBounds;
monitor.PreviewImage = await Task.Run(() => DrawHelper.DrawPreview(this, new Rectangle((int)rect.Left, (int)rect.Top, (int)(rect.Right - rect.Left), (int)(rect.Bottom - rect.Top))));
}
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()

View File

@@ -171,45 +171,12 @@
HorizontalAlignment="Stretch"
Background="{DynamicResource MonitorViewBackgroundBrush}"
CornerRadius="5">
<ScrollViewer
HorizontalAlignment="Center"
HorizontalScrollBarVisibility="Auto">
<ItemsControl
ItemsSource="{Binding Monitors, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
IsItemsHost="True"
Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="models:MonitorSetup">
<Grid
Margin="20,20,20,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding MonitorInfoWithResolution}" Foreground="{DynamicResource PrimaryForegroundBrush}" FontSize="16" FontWeight="Normal" Margin="0,5,0,5"/>
<Border
Grid.Row="1"
CornerRadius="5"
BorderBrush="{DynamicResource TertiaryBackgroundBrush}"
BorderThickness="2"
Margin="0,0,0,10">
<Image
Width="200"
Height="140"
Source="{Binding PreviewImage, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Stretch="Fill"
Margin="2"/>
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<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"

View File

@@ -23,12 +23,29 @@ namespace ProjectsEditor.Utils
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);
@@ -63,7 +80,22 @@ namespace ProjectsEditor.Utils
app.OnPropertyChanged(new PropertyChangedEventArgs("RepeatIndexString"));
}
Bitmap previewBitmap = new Bitmap(Scaled(bounds.Width), Scaled(bounds.Height * 1.2));
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))
{
@@ -71,26 +103,32 @@ namespace ProjectsEditor.Utils
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.Clear(Color.FromArgb(0, 0, 0, 0));
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(Scaled(app.ScaledPosition.X - bounds.Left), Scaled(app.ScaledPosition.Y - bounds.Top), Scaled(app.ScaledPosition.Width), Scaled(app.ScaledPosition.Height));
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(Scaled(app.ScaledPosition.X - bounds.Left), Scaled(app.ScaledPosition.Y - bounds.Top), Scaled(app.ScaledPosition.Width), Scaled(app.ScaledPosition.Height));
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), Scaled(bounds.Width), Scaled(bounds.Height * 0.2));
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));
}

View File

@@ -157,6 +157,7 @@ namespace ProjectsEditor.ViewModels
{
editedProject.Name = projectToSave.Name;
editedProject.IsShortcutNeeded = projectToSave.IsShortcutNeeded;
editedProject.PreviewIcons = projectToSave.PreviewIcons;
editedProject.PreviewImage = projectToSave.PreviewImage;
for (int appIndex = editedProject.Applications.Count - 1; appIndex >= 0; appIndex--)
{
@@ -249,10 +250,7 @@ namespace ProjectsEditor.ViewModels
var editPage = new ProjectEditor(this);
SetEditedProject(selectedProject);
Project projectEdited = new Project(selectedProject) { EditorWindowTitle = isNewlyCreated ? Properties.Resources.CreateProject : Properties.Resources.EditProject };
if (isNewlyCreated)
{
projectEdited.Initialize();
}
projectEdited.Initialize();
editPage.DataContext = projectEdited;
_mainWindow.ShowPage(editPage);