Add a block map (a colored grid where each block can be one or more blocks in the grid).

This commit is contained in:
2019-04-21 16:39:51 +01:00
parent e2d745db4a
commit b0efcddd25
2 changed files with 142 additions and 15 deletions

View File

@@ -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<ColoredBlock>();
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<ColoredBlock> 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();
}
}
}

View File

@@ -14,10 +14,13 @@ namespace DiscImageChef.Gui.Controls
/// </summary>
const int BLOCK_SIZE = 5;
Color gridColor;
public ColoredGrid()
{
ColoredBlocks = new ObservableCollection<ColoredBlock>();
ColoredBlocks.CollectionChanged += (sender, args) => Invalidate();
gridColor = Colors.Black;
}
new bool CanFocus => false;
@@ -32,7 +35,18 @@ namespace DiscImageChef.Gui.Controls
/// <summary>
/// How many blocks are in the grid
/// </summary>
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<ColoredBlock> 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
/// </summary>
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;