Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Selecting Wavelist Models and Allow changing order with Drag&Drop #38

Merged
merged 1 commit into from
Jan 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions src/OneWare.WaveFormViewer/Behaviors/WaveListDropBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.VisualTree;
using Avalonia.Xaml.Interactions.DragAndDrop;
using OneWare.Vcd.Parser.Data;
using OneWare.WaveFormViewer.Models;
using OneWare.WaveFormViewer.ViewModels;

namespace OneWare.WaveFormViewer.Behaviors;

public class WaveListDropBehavior: DropHandlerBase
{
public override void Enter(object? sender, DragEventArgs e, object? sourceContext, object? targetContext)
{
base.Enter(sender, e, sourceContext, targetContext);
if (e.DragEffects == DragDropEffects.None) e.Handled = false;
}

public override void Over(object? sender, DragEventArgs e, object? sourceContext, object? targetContext)
{
base.Over(sender, e, sourceContext, targetContext);
if (e.DragEffects == DragDropEffects.None) e.Handled = false;
}

public override void Drop(object? sender, DragEventArgs e, object? sourceContext, object? targetContext)
{
base.Drop(sender, e, sourceContext, targetContext);
if (e.DragEffects == DragDropEffects.None) e.Handled = false;
}

private bool Validate<T>(ListBox listBox, DragEventArgs e, object? sourceContext, object? targetContext, bool bExecute) where T : WaveModel
{
if (sourceContext is not T sourceItem
|| targetContext is not WaveFormViewModel vm
|| listBox.GetVisualAt(e.GetPosition(listBox)) is not Control targetControl
|| targetControl.DataContext is not T targetItem)
{
return false;
}

var items = vm.Signals;
var sourceIndex = items.IndexOf(sourceItem);
var targetIndex = items.IndexOf(targetItem);

if (sourceIndex < 0 || targetIndex < 0)
{
return false;
}

switch (e.DragEffects)
{
case DragDropEffects.Copy:
{
return false;
}
case DragDropEffects.Move:
{
if (bExecute)
{
MoveItem(items, sourceIndex, targetIndex);
}
return true;
}
case DragDropEffects.Link:
{
if (bExecute)
{
SwapItem(items, sourceIndex, targetIndex);
}
return true;
}
default:
return false;
}
}

public override bool Validate(object? sender, DragEventArgs e, object? sourceContext, object? targetContext, object? state)
{
if (e.Source is Control && sender is ListBox listBox)
{
return Validate<WaveModel>(listBox, e, sourceContext, targetContext, false);
}
return false;
}

public override bool Execute(object? sender, DragEventArgs e, object? sourceContext, object? targetContext, object? state)
{
if (e.Source is Control && sender is ListBox listBox)
{
return Validate<WaveModel>(listBox, e, sourceContext, targetContext, true);
}
return false;
}
}
104 changes: 55 additions & 49 deletions src/OneWare.WaveFormViewer/Controls/WaveFormScale.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class WaveFormScale : Control
private readonly IPen _markerBrushPen;

private CompositeDisposable _disposableReg = new();

private const int MinScaleNumberWidth = 150;

public WaveFormScale()
Expand All @@ -49,65 +49,69 @@ protected override void OnDataContextChanged(EventArgs e)
}

public static List<Marker> CalculateMarkers(long beginOffset, long endOffset, int maxMainMarkers)
{
var markers = new List<Marker>();

if (beginOffset >= endOffset || maxMainMarkers <= 0)
return markers;

var range = (double)(endOffset - beginOffset);
var mainStep = FindBeautifulStep(range, maxMainMarkers);
var intermediateStep = (mainStep / 10);

var firstMainMarker = Math.Ceiling(beginOffset / mainStep) * mainStep;

for (var i = firstMainMarker; i >= beginOffset; i -= intermediateStep)
{
markers.Insert(0, new Marker { Position = (long)i, IsMainMarker = false });
}
var markers = new List<Marker>();

for (var mainMarker = (long)firstMainMarker; mainMarker <= endOffset; mainMarker += (long)mainStep)
{
markers.Add(new Marker { Position = mainMarker, IsMainMarker = true });
if (beginOffset >= endOffset || maxMainMarkers <= 0)
return markers;

var range = (double)(endOffset - beginOffset);
var mainStep = FindBeautifulStep(range, maxMainMarkers);

// Add intermediate markers
for (var i = 1; i < 10; i++)
//TODO Investigate why this could happen
if (mainStep < 1) mainStep = 1;

var intermediateStep = (mainStep / 10);

var firstMainMarker = Math.Ceiling(beginOffset / mainStep) * mainStep;

for (var i = firstMainMarker; i >= beginOffset; i -= intermediateStep)
{
var intermediateMarker = mainMarker + i * intermediateStep;
if (intermediateMarker < endOffset && intermediateMarker > beginOffset)
markers.Insert(0, new Marker { Position = (long)i, IsMainMarker = false });
}

for (var mainMarker = (long)firstMainMarker; mainMarker <= endOffset; mainMarker += (long)mainStep)
{
markers.Add(new Marker { Position = mainMarker, IsMainMarker = true });

// Add intermediate markers
for (var i = 1; i < 10; i++)
{
markers.Add(new Marker { Position = (long)intermediateMarker, IsMainMarker = false });
var intermediateMarker = mainMarker + i * intermediateStep;
if (intermediateMarker < endOffset && intermediateMarker > beginOffset)
{
markers.Add(new Marker { Position = (long)intermediateMarker, IsMainMarker = false });
}
}
}
}

return markers;
}
return markers;
}

private static double FindBeautifulStep(double range, int maxMainMarkers)
{
double[] beautifulNumbers = { 1, 2, 5, 10 };
var targetStepSize = range / (maxMainMarkers - 1);
private static double FindBeautifulStep(double range, int maxMainMarkers)
{
double[] beautifulNumbers = { 1, 2, 5, 10 };
var targetStepSize = range / (maxMainMarkers - 1);

var exponent = (int)Math.Floor(Math.Log10(targetStepSize));
var scale = Math.Pow(10, exponent);
var exponent = (int)Math.Floor(Math.Log10(targetStepSize));
var scale = Math.Pow(10, exponent);

var bestStep = scale;
var minDifference = double.MaxValue;
var bestStep = scale;
var minDifference = double.MaxValue;

foreach (var factor in beautifulNumbers)
{
var currentStep = scale * factor;
var difference = Math.Abs(currentStep - targetStepSize);
if (difference < minDifference)
foreach (var factor in beautifulNumbers)
{
minDifference = difference;
bestStep = currentStep;
var currentStep = scale * factor;
var difference = Math.Abs(currentStep - targetStepSize);
if (difference < minDifference)
{
minDifference = difference;
bestStep = currentStep;
}
}
}

return bestStep;
}
return bestStep;
}

#region Rendering

Expand Down Expand Up @@ -142,7 +146,7 @@ public void DrawScale(DrawingContext context, WaveFormViewModel vm)

var yOffset = 22;
var width = Bounds.Width;

var endOffset = vm.Offset + (long)(width * zm);

var markerX = CalculateMarkers(vm.Offset, endOffset, (int)Bounds.Width / MinScaleNumberWidth);
Expand All @@ -152,7 +156,7 @@ public void DrawScale(DrawingContext context, WaveFormViewModel vm)
new Rect(TextAreaBounds.Width, yOffset, Bounds.Width, Bounds.Height));

if (multiplier == 0) return;

foreach (var mX in markerX)
{
var screenXPosition = (mX.Position - vm.Offset) / zm;
Expand All @@ -162,14 +166,16 @@ public void DrawScale(DrawingContext context, WaveFormViewModel vm)

if (!mX.IsMainMarker)
{
context.DrawLine(_markerBrushPen, new Point(screenXPosition, yOffset - 4), new Point(screenXPosition, yOffset));
context.DrawLine(_markerBrushPen, new Point(screenXPosition, yOffset - 4),
new Point(screenXPosition, yOffset));
}
else
{
var drawT = TimeHelper.FormatTime(mX.Position, vm.TimeScale, vm.ViewPortWidth);

//Big marker
context.DrawLine(_markerBrushPen, new Point(screenXPosition, yOffset - 6), new Point(screenXPosition, Bounds.Height));
context.DrawLine(_markerBrushPen, new Point(screenXPosition, yOffset - 6),
new Point(screenXPosition, Bounds.Height));

var text = new FormattedText(drawT, CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
Typeface.Default,
Expand Down
9 changes: 9 additions & 0 deletions src/OneWare.WaveFormViewer/ViewModels/WaveFormViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,21 @@ public class WaveFormViewModel : ObservableObject
private long _timeScale = 1;

private int _zoomLevel;

private WaveModel? _selectedSignal;

private double _zoomMultiply = 1;
public int MinZoomLevel { get; } = -2;
public int MaxZoomLevel { get; } = 20;

public ObservableCollection<WaveModel> Signals { get; } = [];

public WaveModel? SelectedSignal
{
get => _selectedSignal;
set => SetProperty(ref _selectedSignal, value);
}

/// <summary>
/// 1 = 1 fs
/// </summary>
Expand Down
Loading
Loading