mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Add a block map (a colored grid where each block can be one or more blocks in the grid).
This commit is contained in:
115
DiscImageChef.Gui/Controls/BlockMap.cs
Normal file
115
DiscImageChef.Gui/Controls/BlockMap.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,10 +14,13 @@ namespace DiscImageChef.Gui.Controls
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
const int BLOCK_SIZE = 5;
|
const int BLOCK_SIZE = 5;
|
||||||
|
|
||||||
|
Color gridColor;
|
||||||
|
|
||||||
public ColoredGrid()
|
public ColoredGrid()
|
||||||
{
|
{
|
||||||
ColoredBlocks = new ObservableCollection<ColoredBlock>();
|
ColoredBlocks = new ObservableCollection<ColoredBlock>();
|
||||||
ColoredBlocks.CollectionChanged += (sender, args) => Invalidate();
|
ColoredBlocks.CollectionChanged += (sender, args) => Invalidate();
|
||||||
|
gridColor = Colors.Black;
|
||||||
}
|
}
|
||||||
|
|
||||||
new bool CanFocus => false;
|
new bool CanFocus => false;
|
||||||
@@ -32,7 +35,18 @@ namespace DiscImageChef.Gui.Controls
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// How many blocks are in the grid
|
/// How many blocks are in the grid
|
||||||
/// </summary>
|
/// </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; }
|
public ObservableCollection<ColoredBlock> ColoredBlocks { get; }
|
||||||
|
|
||||||
@@ -48,28 +62,26 @@ namespace DiscImageChef.Gui.Controls
|
|||||||
remainder = (int)rect.Height % (BLOCK_SIZE + 1);
|
remainder = (int)rect.Height % (BLOCK_SIZE + 1);
|
||||||
int height = (int)rect.Height - remainder - 1;
|
int height = (int)rect.Height - remainder - 1;
|
||||||
|
|
||||||
for(float i = rect.X; i <= width; i += 5)
|
for(float i = rect.X; i <= width; i += 5) graphics.DrawLine(gridColor, i, rect.Y, i, height);
|
||||||
graphics.DrawLine(Color.FromRgb(0x00000000), i, rect.Y, i, height);
|
|
||||||
|
|
||||||
for(float i = rect.Y; i <= height; i += 5)
|
for(float i = rect.Y; i <= height; i += 5) graphics.DrawLine(gridColor, rect.X, i, width, i);
|
||||||
graphics.DrawLine(Color.FromRgb(0x00000000), rect.X, i, width, i);
|
|
||||||
|
|
||||||
Columns = width / BLOCK_SIZE;
|
Columns = width / BLOCK_SIZE;
|
||||||
Rows = height / BLOCK_SIZE;
|
Rows = height / BLOCK_SIZE;
|
||||||
Blocks = Columns * Rows;
|
Blocks = (ulong)(Columns * Rows);
|
||||||
|
|
||||||
foreach(ColoredBlock coloredBlock in ColoredBlocks)
|
foreach(ColoredBlock coloredBlock in ColoredBlocks)
|
||||||
PaintBlock(graphics, coloredBlock.Color, coloredBlock.Block);
|
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;
|
if(block > Blocks) return;
|
||||||
|
|
||||||
int row = block / Columns;
|
int row = (int)(block / (ulong)Columns);
|
||||||
int col = block % Columns;
|
int col = (int)(block % (ulong)Columns);
|
||||||
int x = col * BLOCK_SIZE;
|
int x = col * BLOCK_SIZE;
|
||||||
int y = row * BLOCK_SIZE;
|
int y = row * BLOCK_SIZE;
|
||||||
|
|
||||||
graphics.FillRectangle(color, x + 1, y + 1, BLOCK_SIZE - 1, BLOCK_SIZE - 1);
|
graphics.FillRectangle(color, x + 1, y + 1, BLOCK_SIZE - 1, BLOCK_SIZE - 1);
|
||||||
}
|
}
|
||||||
@@ -80,10 +92,10 @@ namespace DiscImageChef.Gui.Controls
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ColoredBlock
|
public class ColoredBlock
|
||||||
{
|
{
|
||||||
public readonly int Block;
|
public readonly ulong Block;
|
||||||
public readonly Color Color;
|
public readonly Color Color;
|
||||||
|
|
||||||
public ColoredBlock(int block, Color color)
|
public ColoredBlock(ulong block, Color color)
|
||||||
{
|
{
|
||||||
Block = block;
|
Block = block;
|
||||||
Color = color;
|
Color = color;
|
||||||
|
|||||||
Reference in New Issue
Block a user