mirror of
https://github.com/4sval/FModel.git
synced 2026-03-25 11:15:23 -05:00
* feat(images): Migrate BitmapImage/ImageSource to Avalonia.Media.Imaging.Bitmap [P2-011] Replace WPF image types in the three affected ViewModels with their Avalonia.Media.Imaging.Bitmap equivalents. Closes #24. TabControlViewModel.cs (TabImage): - Remove 'using System.Windows' and 'using System.Windows.Media.Imaging' - Add 'using Avalonia.Media.Imaging' - BitmapImage _image / public BitmapImage Image -> Bitmap - Both SetImage overloads (SKBitmap and CTexture): replace BeginInit/CacheOption/StreamSource/EndInit/Freeze pattern with 'Image = new Bitmap(stream)'. Bitmap reads the stream into an internal buffer at construction; disposing the MemoryStream after is safe. GameFileViewModel.cs: - Remove 'using System.Windows', '.Windows.Media', '.Windows.Media.Imaging' - Add 'using Avalonia.Media.Imaging', 'using Avalonia.Threading' - ImageSource _previewImage / public ImageSource PreviewImage -> Bitmap - SetPreviewImage: replace WPF BitmapImage construction + Application.Current.Dispatcher.InvokeAsync with new Bitmap(stream) + Dispatcher.UIThread.Post. Bitmap is immutable and not UI-thread-affine; constructing on the background Thread and posting the property assignment is safe. CustomDirectoriesViewModel.cs: - Remove 'using System.Windows', '.Windows.Controls', '.Windows.Media.Imaging' - Add 'using Avalonia.Controls', 'using Avalonia.Layout', 'using Avalonia.Media.Imaging', 'using Avalonia.Platform' - MenuItem/Image/Separator/Control -> Avalonia equivalents (same class names, different namespaces) - BitmapImage(new Uri('/FModel;component/Resources/xxx.png')) -> new Bitmap(AssetLoader.Open(new Uri('avares://FModel/...'))) for the four directory-icon menu items * fix(images): Address PR #79 review findings [P2-011] FModel.csproj [C1]: - Change <Resource> to <AvaloniaResource> for the four directory icon PNGs (add_directory, delete, edit, go_to_directory). WPF <Resource> items are not processed into Avalonia's avares resource manifest, so AssetLoader.Open would have thrown at runtime on every app startup. GameFileViewModel.cs [m1 + PR comment]: - Remove redundant 'ms.Position = 0' in SetPreviewImage: MemoryStream initializes to position 0, making the reset a no-op. - Fix 'Resolved |= ~EResolveCompute.Preview' to 'Resolved &= ~...'. The bitwise-NOT operator on an enum value produces a large negative int, ORing in undefined bits; ORing never clears bits, so the intent (undo the premature Preview flag set at the top of ResolveByExtensionAsync) required &= ~, not |= ~. CustomDirectoriesViewModel.cs [PR comment]: - Extract private static LoadIcon(string filename) helper to wrap each AssetLoader.Open call in a using, ensuring the stream returned by AssetLoader.Open is disposed after Bitmap copies its data. [m2] (Bitmap disposal in Image/PreviewImage setters) is intentionally deferred: disposing the old Bitmap in the setter while the Avalonia render thread may still hold it for the current frame risks a crash. * fix(magnifier): Address review findings [M1, m1, m2, S1] MagnifierManager.cs [M1]: - Replace AdornerLayer.SetAdornment(element, adorner) / SetAdornment(element, null) with AdornerLayer.SetAdornedElement + layer.Children.Add in VerifyAdornerLayer and Parent-cast + Children.Remove in Detach(). SetAdornment is a single-slot API that silently evicts any other adornment on the same element; the collection API matches WPF's AdornerLayer.Add/Remove semantics and allows co-existing adorners. MagnifierManager.cs [S1]: - Set e.Handled = true after a zoom change when the adorner is visible so that a parent ScrollViewer does not also scroll while the user is zooming the magnifier. - Adjust the zoom-out floor from 0 to ZoomFactorOnMouseWheel now that the ZoomFactor validator rejects values <= 0. - Only call UpdateViewBox when the adorner is visible (no-op otherwise). Magnifier.cs [m1]: - Change ZoomFactor validate: v >= 0 -> v > 0. ZoomFactor = 0 produced a zero-sized SourceRect on the VisualBrush which rendered undefined content. The minimum meaningful zoom is any positive value. MagnifierAdorner.cs [m2]: - Return early from HandlePointerEvent when Bounds.Width and Bounds.Height are both 0: the first PointerPressed arrives before the adorner canvas has been through a layout pass, so GetPosition(this) returns meaningless coordinates. The subsequent PointerMoved fires after layout and picks up correct values. * Fix reviewer to stop it getting confused |
||
|---|---|---|
| .. | ||
| agents | ||
| ISSUE_TEMPLATE | ||
| workflows | ||
| FUNDING.yml | ||