diff --git a/DiscImageChef.Gui/Controls/BlockMap.cs b/DiscImageChef.Gui/Controls/BlockMap.cs new file mode 100644 index 000000000..09c3e669c --- /dev/null +++ b/DiscImageChef.Gui/Controls/BlockMap.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Linq; + +namespace DiscImageChef.Gui.Controls +{ + public class BlockMap : ColoredGrid + { + ulong _sectors; + public uint blocksToRead; + + public uint sectorsToRead; + + public BlockMap() + { + ColoredSectors = new ObservableCollection(); + ColoredSectors.CollectionChanged += OnColoredSectorsChanged; + } + + public ulong Sectors + { + get => _sectors; + set + { + _sectors = value; + CalculateBoundaries(); + Invalidate(); + } + } + + public ulong SectorsPerBlock { get; private set; } + + public uint SectorsToRead + { + get => sectorsToRead; + set + { + sectorsToRead = value; + blocksToRead = (uint)(sectorsToRead / SectorsPerBlock); + if(sectorsToRead % SectorsPerBlock > 0) blocksToRead++; + } + } + + public ObservableCollection ColoredSectors { get; } + + void OnColoredSectorsChanged(object sender, NotifyCollectionChangedEventArgs args) + { + switch(args.Action) + { + case NotifyCollectionChangedAction.Add: + foreach(object item in args.NewItems) + { + if(!(item is ColoredBlock block)) continue; + + for(ulong i = 0; i < blocksToRead; i++) + ColoredBlocks.Add(new ColoredBlock(block.Block / SectorsPerBlock + i, block.Color)); + } + + break; + case NotifyCollectionChangedAction.Move: break; + case NotifyCollectionChangedAction.Remove: + foreach(object item in args.OldItems) + { + if(!(item is ColoredBlock block)) continue; + + for(ulong i = 0; i < blocksToRead; i++) + ColoredBlocks.Remove(ColoredBlocks.FirstOrDefault(t => t.Block == block.Block / + SectorsPerBlock + i)); + } + + break; + case NotifyCollectionChangedAction.Replace: + foreach(object item in args.OldItems) + { + if(!(item is ColoredBlock block)) continue; + + for(ulong i = 0; i < blocksToRead; i++) + ColoredBlocks.Remove(ColoredBlocks.FirstOrDefault(t => t.Block == block.Block / + SectorsPerBlock + i)); + } + + foreach(object item in args.NewItems) + { + if(!(item is ColoredBlock block)) continue; + + for(ulong i = 0; i < blocksToRead; i++) + ColoredBlocks.Add(new ColoredBlock(block.Block / SectorsPerBlock + i, block.Color)); + } + + break; + case NotifyCollectionChangedAction.Reset: + ColoredBlocks.Clear(); + break; + default: throw new ArgumentOutOfRangeException(); + } + } + + void CalculateBoundaries() + { + SectorsPerBlock = Blocks == 0 ? 0 : _sectors / Blocks; + ColoredBlocks.Clear(); + + if(SectorsPerBlock > 0) return; + + SectorsPerBlock = 1; + for(ulong i = Sectors; i < Blocks; i++) ColoredBlocks.Add(new ColoredBlock(i, GridColor)); + } + + public void Clear() + { + ColoredSectors.Clear(); + } + } +} \ No newline at end of file diff --git a/DiscImageChef.Gui/Controls/ColoredGrid.cs b/DiscImageChef.Gui/Controls/ColoredGrid.cs index 48dbe007c..005866ef4 100644 --- a/DiscImageChef.Gui/Controls/ColoredGrid.cs +++ b/DiscImageChef.Gui/Controls/ColoredGrid.cs @@ -14,10 +14,13 @@ namespace DiscImageChef.Gui.Controls /// const int BLOCK_SIZE = 5; + Color gridColor; + public ColoredGrid() { ColoredBlocks = new ObservableCollection(); ColoredBlocks.CollectionChanged += (sender, args) => Invalidate(); + gridColor = Colors.Black; } new bool CanFocus => false; @@ -32,7 +35,18 @@ namespace DiscImageChef.Gui.Controls /// /// How many blocks are in the grid /// - public int Blocks { get; private set; } + public ulong Blocks { get; private set; } + public Color GridColor + { + get => gridColor; + set + { + if(gridColor == value) return; + + gridColor = value; + Invalidate(); + } + } public ObservableCollection ColoredBlocks { get; } @@ -48,28 +62,26 @@ namespace DiscImageChef.Gui.Controls remainder = (int)rect.Height % (BLOCK_SIZE + 1); int height = (int)rect.Height - remainder - 1; - for(float i = rect.X; i <= width; i += 5) - graphics.DrawLine(Color.FromRgb(0x00000000), i, rect.Y, i, height); + for(float i = rect.X; i <= width; i += 5) graphics.DrawLine(gridColor, i, rect.Y, i, height); - for(float i = rect.Y; i <= height; i += 5) - graphics.DrawLine(Color.FromRgb(0x00000000), rect.X, i, width, i); + for(float i = rect.Y; i <= height; i += 5) graphics.DrawLine(gridColor, rect.X, i, width, i); - Columns = width / BLOCK_SIZE; - Rows = height / BLOCK_SIZE; - Blocks = Columns * Rows; + Columns = width / BLOCK_SIZE; + Rows = height / BLOCK_SIZE; + Blocks = (ulong)(Columns * Rows); foreach(ColoredBlock coloredBlock in ColoredBlocks) PaintBlock(graphics, coloredBlock.Color, coloredBlock.Block); } - void PaintBlock(Graphics graphics, Color color, int block) + void PaintBlock(Graphics graphics, Color color, ulong block) { if(block > Blocks) return; - int row = block / Columns; - int col = block % Columns; - int x = col * BLOCK_SIZE; - int y = row * BLOCK_SIZE; + int row = (int)(block / (ulong)Columns); + int col = (int)(block % (ulong)Columns); + int x = col * BLOCK_SIZE; + int y = row * BLOCK_SIZE; graphics.FillRectangle(color, x + 1, y + 1, BLOCK_SIZE - 1, BLOCK_SIZE - 1); } @@ -80,10 +92,10 @@ namespace DiscImageChef.Gui.Controls /// public class ColoredBlock { - public readonly int Block; + public readonly ulong Block; public readonly Color Color; - public ColoredBlock(int block, Color color) + public ColoredBlock(ulong block, Color color) { Block = block; Color = color;