Skip to content

Commit 0d2aab0

Browse files
committed
GC init alpha version
1 parent 3540c2c commit 0d2aab0

4 files changed

Lines changed: 237 additions & 16 deletions

File tree

GarbageCollector.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
<Nullable>enable</Nullable>
77
<ImplicitUsings>enable</ImplicitUsings>
88
<UseWPF>true</UseWPF>
9+
<ApplicationIcon>Resources\app.ico</ApplicationIcon>
910
</PropertyGroup>
1011

12+
<ItemGroup>
13+
<Content Include="Resources\app.ico" />
14+
</ItemGroup>
15+
1116
</Project>

MainWindow.xaml

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
11
<Window x:Class="GarbageCollector.MainWindow"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4-
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5-
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6-
xmlns:local="clr-namespace:GarbageCollector"
7-
mc:Ignorable="d"
8-
Title="MainWindow" Height="450" Width="800">
9-
<Grid>
4+
Title="GarbageCollector Alpha Testing" Height="550" Width="700">
5+
<Grid Margin="10">
6+
<Grid.RowDefinitions>
7+
<RowDefinition Height="*"/>
8+
<RowDefinition Height="Auto"/>
9+
</Grid.RowDefinitions>
1010

11+
<ListBox x:Name="FileList" SelectionMode="Single" MouseDoubleClick="FileList_MouseDoubleClick">
12+
<ListBox.ItemTemplate>
13+
<DataTemplate>
14+
<StackPanel Orientation="Horizontal" Margin="2">
15+
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" VerticalAlignment="Center" Margin="5"/>
16+
<Image Source="{Binding Icon}" Width="20" Height="20" Margin="4,0" VerticalAlignment="Center"/>
17+
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="8,0"/>
18+
</StackPanel>
19+
</DataTemplate>
20+
</ListBox.ItemTemplate>
21+
</ListBox>
22+
23+
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" Margin="5">
24+
<Button Content="Delete Selected" Click="DeleteSelected_Click" Margin="5" Padding="10,5"/>
25+
<Button Content="Organize by Type" Click="OrganizeByType_Click" Margin="5" Padding="10,5"/>
26+
<Button Content="Refresh" Click="Refresh_Click" Margin="5" Padding="10,5"/>
27+
</StackPanel>
1128
</Grid>
1229
</Window>

MainWindow.xaml.cs

Lines changed: 209 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,223 @@
1-
using System.Text;
1+
using Microsoft.VisualBasic.FileIO;
2+
using System;
3+
using System.Collections.ObjectModel;
4+
using System.Diagnostics;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Runtime.InteropServices;
28
using System.Windows;
3-
using System.Windows.Controls;
4-
using System.Windows.Data;
5-
using System.Windows.Documents;
69
using System.Windows.Input;
10+
using System.Windows.Interop;
711
using System.Windows.Media;
812
using System.Windows.Media.Imaging;
9-
using System.Windows.Navigation;
10-
using System.Windows.Shapes;
1113

1214
namespace GarbageCollector
1315
{
14-
/// <summary>
15-
/// Interaction logic for MainWindow.xaml
16-
/// </summary>
1716
public partial class MainWindow : Window
1817
{
18+
private readonly string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
19+
public ObservableCollection<FileItem> Files { get; set; } = new ObservableCollection<FileItem>();
20+
1921
public MainWindow()
2022
{
2123
InitializeComponent();
24+
LoadFiles();
25+
}
26+
27+
private void LoadFiles()
28+
{
29+
Files.Clear();
30+
31+
// Add folders
32+
foreach (var dir in Directory.GetDirectories(desktopPath))
33+
{
34+
Files.Add(new FileItem
35+
{
36+
Name = Path.GetFileName(dir),
37+
FullPath = dir,
38+
Icon = IconHelper.GetIcon(dir, true),
39+
IsFolder = true
40+
});
41+
}
42+
43+
// Add files
44+
foreach (var file in Directory.GetFiles(desktopPath))
45+
{
46+
Files.Add(new FileItem
47+
{
48+
Name = Path.GetFileName(file),
49+
FullPath = file,
50+
Icon = IconHelper.GetIcon(file, false),
51+
IsFolder = false
52+
});
53+
}
54+
55+
FileList.ItemsSource = Files;
56+
}
57+
58+
private void DeleteSelected_Click(object sender, RoutedEventArgs e)
59+
{
60+
var selected = Files.Where(f => f.IsChecked).ToList();
61+
if (!selected.Any())
62+
{
63+
MessageBox.Show("No items selected.", "GarbageCollector", MessageBoxButton.OK, MessageBoxImage.Information);
64+
return;
65+
}
66+
67+
// CONFIRMATION
68+
var result = MessageBox.Show(
69+
$"Are you sure you want to delete {selected.Count} selected item(s)? They will be sent to the Recycle Bin.",
70+
"Confirm Delete",
71+
MessageBoxButton.YesNo,
72+
MessageBoxImage.Warning);
73+
74+
if (result != MessageBoxResult.Yes) return;
75+
76+
foreach (var f in selected)
77+
{
78+
try
79+
{
80+
if (f.IsFolder)
81+
{
82+
Microsoft.VisualBasic.FileIO.FileSystem.DeleteDirectory(f.FullPath,
83+
Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs,
84+
Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin);
85+
}
86+
else
87+
{
88+
Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile(f.FullPath,
89+
Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs,
90+
Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin);
91+
}
92+
}
93+
catch (Exception ex)
94+
{
95+
MessageBox.Show($"Error deleting {f.Name}: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
96+
}
97+
}
98+
99+
LoadFiles();
100+
}
101+
102+
103+
private void OrganizeByType_Click(object sender, RoutedEventArgs e)
104+
{
105+
// CONFIRMATION
106+
var result = MessageBox.Show(
107+
"Are you sure you want to organize your desktop files into folders by type?",
108+
"Confirm Organize",
109+
MessageBoxButton.YesNo,
110+
MessageBoxImage.Question);
111+
112+
if (result != MessageBoxResult.Yes) return;
113+
114+
foreach (var file in Directory.GetFiles(desktopPath))
115+
{
116+
string ext = Path.GetExtension(file).Trim('.').ToUpper();
117+
if (string.IsNullOrEmpty(ext)) ext = "OTHERS";
118+
119+
string folder = Path.Combine(desktopPath, ext);
120+
Directory.CreateDirectory(folder);
121+
122+
string destPath = Path.Combine(folder, Path.GetFileName(file));
123+
try
124+
{
125+
if (!File.Exists(destPath))
126+
File.Move(file, destPath);
127+
}
128+
catch (Exception ex)
129+
{
130+
MessageBox.Show($"Error moving {file}: {ex.Message}");
131+
}
132+
}
133+
LoadFiles();
134+
}
135+
136+
137+
private void Refresh_Click(object sender, RoutedEventArgs e) => LoadFiles();
138+
139+
private void FileList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
140+
{
141+
if (FileList.SelectedItem is FileItem item)
142+
{
143+
try
144+
{
145+
var psi = new ProcessStartInfo
146+
{
147+
FileName = item.FullPath,
148+
UseShellExecute = true
149+
};
150+
Process.Start(psi);
151+
}
152+
catch (Exception ex)
153+
{
154+
MessageBox.Show($"Cannot open {item.Name}: {ex.Message}");
155+
}
156+
}
157+
}
158+
}
159+
160+
// ========== FileItem ==========
161+
public class FileItem
162+
{
163+
public string Name { get; set; }
164+
public string FullPath { get; set; }
165+
public bool IsFolder { get; set; }
166+
public bool IsChecked { get; set; }
167+
public ImageSource Icon { get; set; }
168+
}
169+
170+
// ========== IconHelper ==========
171+
internal static class IconHelper
172+
{
173+
private const uint SHGFI_ICON = 0x000000100;
174+
private const uint SHGFI_SMALLICON = 0x000000001;
175+
private const uint FILE_ATTRIBUTE_DIRECTORY = 0x10;
176+
private const uint FILE_ATTRIBUTE_NORMAL = 0x80;
177+
178+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
179+
private struct SHFILEINFO
180+
{
181+
public IntPtr hIcon;
182+
public int iIcon;
183+
public uint dwAttributes;
184+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
185+
public string szDisplayName;
186+
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
187+
public string szTypeName;
188+
}
189+
190+
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
191+
private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
192+
193+
[DllImport("user32.dll", SetLastError = true)]
194+
private static extern bool DestroyIcon(IntPtr hIcon);
195+
196+
public static ImageSource GetIcon(string path, bool isFolder)
197+
{
198+
try
199+
{
200+
SHFILEINFO shinfo = new SHFILEINFO();
201+
uint flags = SHGFI_ICON | SHGFI_SMALLICON;
202+
uint attrs = isFolder ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
203+
204+
SHGetFileInfo(path, attrs, ref shinfo, (uint)Marshal.SizeOf(shinfo), flags);
205+
if (shinfo.hIcon != IntPtr.Zero)
206+
{
207+
var img = Imaging.CreateBitmapSourceFromHIcon(
208+
shinfo.hIcon,
209+
Int32Rect.Empty,
210+
BitmapSizeOptions.FromWidthAndHeight(16, 16));
211+
img.Freeze();
212+
DestroyIcon(shinfo.hIcon);
213+
return img;
214+
}
215+
}
216+
catch
217+
{
218+
// fallback: no icon
219+
}
220+
return null;
22221
}
23222
}
24-
}
223+
}

Resources/app.ico

115 KB
Binary file not shown.

0 commit comments

Comments
 (0)