mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-27 00:07:58 +01:00
Refactoring... WIP 3
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
#nullable enable
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Terminal.Gui;
|
||||
|
||||
@@ -39,8 +38,7 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
OnOrientationChanged (Orientation);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <inheritdoc/>
|
||||
protected override void OnSubviewLayout (LayoutEventArgs args)
|
||||
{
|
||||
if (ViewportDimension < 1)
|
||||
@@ -49,10 +47,12 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
|
||||
return;
|
||||
}
|
||||
_slider.Size = (int)Math.Clamp (Math.Floor ((double)ViewportDimension * ViewportDimension / (Size)), 1, ViewportDimension);
|
||||
|
||||
_slider.Size = (int)Math.Clamp (Math.Floor ((double)ViewportDimension * ViewportDimension / (Size - 2)), 1, ViewportDimension);
|
||||
}
|
||||
|
||||
#region IOrientation members
|
||||
|
||||
private readonly OrientationHelper _orientationHelper;
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -133,16 +133,16 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
/// <summary>Raised when <see cref="Size"/> has changed.</summary>
|
||||
public event EventHandler<EventArgs<int>>? SizeChanged;
|
||||
|
||||
private int _sliderPosition;
|
||||
|
||||
#region SliderPosition
|
||||
private void OnSliderOnFrameChanged (object? sender, EventArgs<Rectangle> args)
|
||||
{
|
||||
if (ViewportDimension == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int framePos = Orientation == Orientation.Vertical ? args.CurrentValue.Y : args.CurrentValue.X;
|
||||
RaisePositionChangeEvents (_sliderPosition, framePos);
|
||||
SliderPosition = framePos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -150,57 +150,23 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
/// </summary>
|
||||
public int SliderPosition
|
||||
{
|
||||
get => _sliderPosition;
|
||||
set => RaisePositionChangeEvents (_sliderPosition, value);
|
||||
get => CalculateSliderPosition (_contentPosition);
|
||||
set => RaiseSliderPositionChangeEvents (value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position of the ScrollSlider within the range of 0...<see cref="Size"/>.
|
||||
/// </summary>
|
||||
public int ContentPosition
|
||||
private void RaiseSliderPositionChangeEvents (int newSliderPosition)
|
||||
{
|
||||
get
|
||||
int currentSliderPosition = CalculateSliderPosition (_contentPosition);
|
||||
|
||||
if (newSliderPosition > Size - ViewportDimension)
|
||||
{
|
||||
if (ViewportDimension - _slider.Size == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (int)Math.Round (GetCurrentContentPosition ());
|
||||
return;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Size - ViewportDimension == 0)
|
||||
{
|
||||
SliderPosition = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
double newContentPos = (double)value / (ViewportDimension - _slider.Size) * (Size - ViewportDimension);
|
||||
double newSliderPos = (double)value / (Size - ViewportDimension) * (ViewportDimension - _slider.Size);
|
||||
|
||||
int newSliderPosition = (int)Math.Ceiling (newSliderPos);
|
||||
if (newContentPos >= GetCurrentContentPosition ())
|
||||
{
|
||||
newSliderPosition = (int)Math.Floor (newSliderPos);
|
||||
}
|
||||
|
||||
if (SliderPosition != newSliderPosition)
|
||||
{
|
||||
SliderPosition = newSliderPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private double GetCurrentContentPosition ()
|
||||
{
|
||||
return (double)SliderPosition / (ViewportDimension - _slider.Size) * (Size - ViewportDimension);
|
||||
}
|
||||
|
||||
private void RaisePositionChangeEvents (int currentSliderPosition, int newSliderPosition)
|
||||
{
|
||||
if (OnPositionChanging (currentSliderPosition, newSliderPosition))
|
||||
if (OnSliderPositionChanging (currentSliderPosition, newSliderPosition))
|
||||
{
|
||||
_slider.Position = currentSliderPosition;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -210,30 +176,28 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
if (args.Cancel)
|
||||
{
|
||||
_slider.Position = currentSliderPosition;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// This sets the slider position and clamps the value
|
||||
_slider.Position = newSliderPosition;
|
||||
|
||||
if (_slider.Position == _sliderPosition)
|
||||
if (_slider.Position == currentSliderPosition)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_sliderPosition = newSliderPosition;
|
||||
ContentPosition = (int)Math.Round ((double)newSliderPosition / (ViewportDimension - _slider.Size) * (Size - ViewportDimension));
|
||||
|
||||
OnPositionChanged (_sliderPosition);
|
||||
OnSliderPositionChanged (newSliderPosition);
|
||||
SliderPositionChanged?.Invoke (this, new (in newSliderPosition));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see cref="SliderPosition"/> is changing. Return true to cancel the change.
|
||||
/// </summary>
|
||||
protected virtual bool OnPositionChanging (int currentPos, int newPos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
protected virtual bool OnSliderPositionChanging (int currentSliderPosition, int newSliderPosition) { return false; }
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the <see cref="SliderPosition"/> is changing. Set <see cref="CancelEventArgs.Cancel"/> to
|
||||
@@ -242,11 +206,88 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
public event EventHandler<CancelEventArgs<int>>? SliderPositionChanging;
|
||||
|
||||
/// <summary>Called when <see cref="SliderPosition"/> has changed.</summary>
|
||||
protected virtual void OnPositionChanged (int position) { }
|
||||
protected virtual void OnSliderPositionChanged (int position) { }
|
||||
|
||||
/// <summary>Raised when the <see cref="SliderPosition"/> has changed.</summary>
|
||||
public event EventHandler<EventArgs<int>>? SliderPositionChanged;
|
||||
|
||||
private int CalculateSliderPosition (int contentPosition)
|
||||
{
|
||||
if (Size - ViewportDimension == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)Math.Round ((double)contentPosition / (Size - ViewportDimension) * (ViewportDimension - _slider.Size));
|
||||
}
|
||||
|
||||
#endregion SliderPosition
|
||||
|
||||
#region ContentPosition
|
||||
|
||||
private int _contentPosition;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position of the ScrollSlider within the range of 0...<see cref="Size"/>.
|
||||
/// </summary>
|
||||
public int ContentPosition
|
||||
{
|
||||
get => _contentPosition;
|
||||
set
|
||||
{
|
||||
if (value == _contentPosition)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RaiseContentPositionChangeEvents (value);
|
||||
}
|
||||
}
|
||||
|
||||
private void RaiseContentPositionChangeEvents (int newContentPosition)
|
||||
{
|
||||
// Clamp the value between 0 and Size - ViewportDimension
|
||||
newContentPosition = (int)Math.Clamp (newContentPosition, 0, Size - ViewportDimension);
|
||||
|
||||
if (OnContentPositionChanging (_contentPosition, newContentPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CancelEventArgs<int> args = new (ref _contentPosition, ref newContentPosition);
|
||||
ContentPositionChanging?.Invoke (this, args);
|
||||
|
||||
if (args.Cancel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_contentPosition = newContentPosition;
|
||||
|
||||
SliderPosition = CalculateSliderPosition (_contentPosition);
|
||||
|
||||
OnContentPositionChanged (_contentPosition);
|
||||
ContentPositionChanged?.Invoke (this, new (in _contentPosition));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when <see cref="ContentPosition"/> is changing. Return true to cancel the change.
|
||||
/// </summary>
|
||||
protected virtual bool OnContentPositionChanging (int currentPos, int newPos) { return false; }
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the <see cref="ContentPosition"/> is changing. Set <see cref="CancelEventArgs.Cancel"/> to
|
||||
/// <see langword="true"/> to prevent the position from being changed.
|
||||
/// </summary>
|
||||
public event EventHandler<CancelEventArgs<int>>? ContentPositionChanging;
|
||||
|
||||
/// <summary>Called when <see cref="ContentPosition"/> has changed.</summary>
|
||||
protected virtual void OnContentPositionChanged (int position) { }
|
||||
|
||||
/// <summary>Raised when the <see cref="ContentPosition"/> has changed.</summary>
|
||||
public event EventHandler<EventArgs<int>>? ContentPositionChanged;
|
||||
|
||||
#endregion ContentPosition
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool OnClearingViewport ()
|
||||
@@ -256,7 +297,7 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <inheritdoc/>
|
||||
protected override bool OnMouseClick (MouseEventArgs args)
|
||||
{
|
||||
if (!args.IsSingleClicked)
|
||||
@@ -285,7 +326,6 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
SliderPosition = args.Position.X;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -306,29 +346,31 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
{
|
||||
if (mouseEvent.Flags.HasFlag (MouseFlags.WheeledDown))
|
||||
{
|
||||
SliderPosition++;
|
||||
ContentPosition++;
|
||||
}
|
||||
|
||||
if (mouseEvent.Flags.HasFlag (MouseFlags.WheeledUp))
|
||||
{
|
||||
SliderPosition--;
|
||||
ContentPosition--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mouseEvent.Flags.HasFlag (MouseFlags.WheeledRight))
|
||||
{
|
||||
SliderPosition++;
|
||||
ContentPosition++;
|
||||
}
|
||||
|
||||
if (mouseEvent.Flags.HasFlag (MouseFlags.WheeledLeft))
|
||||
{
|
||||
SliderPosition--;
|
||||
ContentPosition--;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <inheritdoc/>
|
||||
public bool EnableForDesign ()
|
||||
{
|
||||
OrientationChanged += (sender, args) =>
|
||||
@@ -348,9 +390,7 @@ public class Scroll : View, IOrientation, IDesignable
|
||||
Width = 1;
|
||||
Height = Dim.Fill ();
|
||||
Size = 1000;
|
||||
SliderPosition = 10;
|
||||
|
||||
|
||||
ContentPosition = 10;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ public class ScrollBar : View, IOrientation, IDesignable
|
||||
_scroll = new ();
|
||||
_scroll.SliderPositionChanging += OnScrollOnSliderPositionChanging;
|
||||
_scroll.SliderPositionChanged += OnScrollOnSliderPositionChanged;
|
||||
_scroll.ContentPositionChanging += OnScrollOnContentPositionChanging;
|
||||
_scroll.ContentPositionChanged += OnScrollOnContentPositionChanged;
|
||||
_scroll.SizeChanged += OnScrollOnSizeChanged;
|
||||
|
||||
_decreaseButton = new ()
|
||||
@@ -64,13 +66,13 @@ public class ScrollBar : View, IOrientation, IDesignable
|
||||
|
||||
void OnDecreaseButtonOnAccept (object? s, CommandEventArgs e)
|
||||
{
|
||||
_scroll.ContentPosition--;
|
||||
ContentPosition -= Increment;
|
||||
e.Cancel = true;
|
||||
}
|
||||
|
||||
void OnIncreaseButtonOnAccept (object? s, CommandEventArgs e)
|
||||
{
|
||||
_scroll.ContentPosition++;
|
||||
ContentPosition += Increment;
|
||||
e.Cancel = true;
|
||||
}
|
||||
}
|
||||
@@ -188,8 +190,8 @@ public class ScrollBar : View, IOrientation, IDesignable
|
||||
set => _scroll.SliderPosition = value;
|
||||
}
|
||||
|
||||
private void OnScrollOnSliderPositionChanged (object? sender, EventArgs<int> e) { SliderPositionChanged?.Invoke (this, e); }
|
||||
private void OnScrollOnSliderPositionChanging (object? sender, CancelEventArgs<int> e) { SliderPositionChanging?.Invoke (this, e); }
|
||||
private void OnScrollOnSliderPositionChanged (object? sender, EventArgs<int> e) { SliderPositionChanged?.Invoke (this, e); }
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the <see cref="SliderPosition"/> is changing. Set <see cref="CancelEventArgs.Cancel"/> to
|
||||
@@ -219,6 +221,18 @@ public class ScrollBar : View, IOrientation, IDesignable
|
||||
set => _scroll.ContentPosition = value;
|
||||
}
|
||||
|
||||
private void OnScrollOnContentPositionChanging (object? sender, CancelEventArgs<int> e) { ContentPositionChanging?.Invoke (this, e); }
|
||||
private void OnScrollOnContentPositionChanged (object? sender, EventArgs<int> e) { ContentPositionChanged?.Invoke (this, e); }
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the <see cref="SliderPosition"/> is changing. Set <see cref="CancelEventArgs.Cancel"/> to
|
||||
/// <see langword="true"/> to prevent the position from being changed.
|
||||
/// </summary>
|
||||
public event EventHandler<CancelEventArgs<int>>? ContentPositionChanging;
|
||||
|
||||
/// <summary>Raised when the <see cref="SliderPosition"/> has changed.</summary>
|
||||
public event EventHandler<EventArgs<int>>? ContentPositionChanged;
|
||||
|
||||
/// <summary>Raised when <see cref="Size"/> has changed.</summary>
|
||||
public event EventHandler<EventArgs<int>>? SizeChanged;
|
||||
|
||||
@@ -228,6 +242,14 @@ public class ScrollBar : View, IOrientation, IDesignable
|
||||
SizeChanged?.Invoke (this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the amount each click of the increment/decrement buttons will incremenet/decrement the <see cref="ContentPosition"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default is 1.
|
||||
/// </remarks>
|
||||
public int Increment { get; set; } = 1;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnSubviewLayout (LayoutEventArgs args) { PositionSubviews (); }
|
||||
|
||||
|
||||
@@ -10,9 +10,7 @@ using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Unicode;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Terminal.Gui;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
using static Terminal.Gui.SpinnerStyle;
|
||||
|
||||
namespace UICatalog.Scenarios;
|
||||
@@ -303,7 +301,7 @@ public class CharacterMap : Scenario
|
||||
|
||||
public override List<Key> GetDemoKeyStrokes ()
|
||||
{
|
||||
List<Key> keys = new List<Key> ();
|
||||
List<Key> keys = new ();
|
||||
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
@@ -345,15 +343,17 @@ internal class CharMap : View, IDesignable
|
||||
ColorScheme = Colors.ColorSchemes ["Dialog"];
|
||||
CanFocus = true;
|
||||
CursorVisibility = CursorVisibility.Default;
|
||||
|
||||
//ViewportSettings = ViewportSettings.AllowLocationGreaterThanContentSize;
|
||||
|
||||
SetContentSize (new (COLUMN_WIDTH * 16, (_maxCodePoint / 16) * _rowHeight)); // +1 for Header
|
||||
SetContentSize (new (COLUMN_WIDTH * 16 + RowLabelWidth, _maxCodePoint / 16 * _rowHeight)); // +1 for Header
|
||||
|
||||
AddCommand (
|
||||
Command.Up,
|
||||
() =>
|
||||
{
|
||||
SelectedCodePoint -= 16;
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
@@ -363,6 +363,7 @@ internal class CharMap : View, IDesignable
|
||||
() =>
|
||||
{
|
||||
SelectedCodePoint += 16;
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
@@ -372,6 +373,7 @@ internal class CharMap : View, IDesignable
|
||||
() =>
|
||||
{
|
||||
SelectedCodePoint--;
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
@@ -380,7 +382,8 @@ internal class CharMap : View, IDesignable
|
||||
Command.Right,
|
||||
() =>
|
||||
{
|
||||
SelectedCodePoint++;
|
||||
SelectedCodePoint++;
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
@@ -455,11 +458,12 @@ internal class CharMap : View, IDesignable
|
||||
_hScrollBar = new ()
|
||||
{
|
||||
AutoHide = false,
|
||||
X = RowLabelWidth + 1,
|
||||
X = RowLabelWidth,
|
||||
Y = Pos.AnchorEnd (),
|
||||
Orientation = Orientation.Horizontal,
|
||||
Width = Dim.Fill (1),
|
||||
Size = GetContentSize ().Width
|
||||
Size = GetContentSize ().Width - RowLabelWidth,
|
||||
Increment = COLUMN_WIDTH
|
||||
};
|
||||
|
||||
_vScrollBar = new ()
|
||||
@@ -473,26 +477,31 @@ internal class CharMap : View, IDesignable
|
||||
|
||||
Padding.Add (_vScrollBar, _hScrollBar);
|
||||
|
||||
_vScrollBar.SliderPositionChanged += (sender, args) =>
|
||||
{
|
||||
if (Viewport.Height > 0)
|
||||
{
|
||||
Viewport = Viewport with { Y = _vScrollBar.ContentPosition };
|
||||
}
|
||||
};
|
||||
_vScrollBar.ContentPositionChanged += (sender, args) =>
|
||||
{
|
||||
if (Viewport.Height > 0)
|
||||
{
|
||||
Viewport = Viewport with
|
||||
{
|
||||
Y = Math.Min (args.CurrentValue, GetContentSize ().Height - (Viewport.Height - 2))
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
_hScrollBar.SliderPositionChanged += (sender, args) =>
|
||||
{
|
||||
if (Viewport.Width > 0)
|
||||
{
|
||||
Viewport = Viewport with { X = _hScrollBar.ContentPosition };
|
||||
}
|
||||
};
|
||||
_hScrollBar.ContentPositionChanged += (sender, args) =>
|
||||
{
|
||||
if (Viewport.Width > 0)
|
||||
{
|
||||
Viewport = Viewport with
|
||||
{
|
||||
X = Math.Min (args.CurrentValue, GetContentSize ().Width - Viewport.Width)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
FrameChanged += (sender, args) =>
|
||||
{
|
||||
int width = Viewport.Width / COLUMN_WIDTH * COLUMN_WIDTH - RowLabelWidth;
|
||||
if (width < GetContentSize ().Width)
|
||||
if (Viewport.Width < GetContentSize ().Width)
|
||||
{
|
||||
Padding.Thickness = Padding.Thickness with { Bottom = 1 };
|
||||
}
|
||||
@@ -500,6 +509,7 @@ internal class CharMap : View, IDesignable
|
||||
{
|
||||
Padding.Thickness = Padding.Thickness with { Bottom = 0 };
|
||||
}
|
||||
|
||||
_hScrollBar.ContentPosition = Viewport.X;
|
||||
_vScrollBar.ContentPosition = Viewport.Y;
|
||||
};
|
||||
@@ -527,7 +537,8 @@ internal class CharMap : View, IDesignable
|
||||
|
||||
if (e.Flags == MouseFlags.WheeledRight)
|
||||
{
|
||||
_hScrollBar.SliderPosition++;
|
||||
ScrollHorizontal (1);
|
||||
_hScrollBar.ContentPosition = Viewport.X;
|
||||
e.Handled = true;
|
||||
|
||||
return;
|
||||
@@ -535,7 +546,8 @@ internal class CharMap : View, IDesignable
|
||||
|
||||
if (e.Flags == MouseFlags.WheeledLeft)
|
||||
{
|
||||
_hScrollBar.SliderPosition--;
|
||||
ScrollHorizontal (-1);
|
||||
_hScrollBar.ContentPosition = Viewport.X;
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
@@ -545,8 +557,8 @@ internal class CharMap : View, IDesignable
|
||||
{
|
||||
get
|
||||
{
|
||||
int row = SelectedCodePoint / 16 * _rowHeight - Viewport.Y + 1; // + 1 for header
|
||||
int col = SelectedCodePoint % 16 * COLUMN_WIDTH - Viewport.X + RowLabelWidth + 1; // + 1 for padding between label and first column
|
||||
int row = SelectedCodePoint / 16 * _rowHeight + 1 - Viewport.Y; // + 1 for header
|
||||
int col = SelectedCodePoint % 16 * COLUMN_WIDTH + RowLabelWidth + 1 - Viewport.X; // + 1 for padding between label and first column
|
||||
|
||||
return new (col, row);
|
||||
}
|
||||
@@ -556,7 +568,8 @@ internal class CharMap : View, IDesignable
|
||||
public static int _maxCodePoint = UnicodeRange.Ranges.Max (r => r.End);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the currently selected codepoint. Causes the Viewport to scroll to make the selected code point visible.
|
||||
/// Gets or sets the currently selected codepoint. Causes the Viewport to scroll to make the selected code point
|
||||
/// visible.
|
||||
/// </summary>
|
||||
public int SelectedCodePoint
|
||||
{
|
||||
@@ -571,58 +584,48 @@ internal class CharMap : View, IDesignable
|
||||
Point prevCursor = Cursor;
|
||||
int newSelectedCodePoint = Math.Clamp (value, 0, _maxCodePoint);
|
||||
|
||||
ScrollToMakeRowVisible (newSelectedCodePoint / 16 * _rowHeight, prevCursor.Y);
|
||||
ScrollToMakeColumnVisible (newSelectedCodePoint % 16 * COLUMN_WIDTH, prevCursor.X);
|
||||
|
||||
if (_selected != newSelectedCodePoint)
|
||||
Point newCursor = new ()
|
||||
{
|
||||
_selected = newSelectedCodePoint;
|
||||
SetNeedsDraw ();
|
||||
SelectedCodePointChanged?.Invoke (this, new (SelectedCodePoint, null));
|
||||
}
|
||||
X = newSelectedCodePoint % 16 * COLUMN_WIDTH + RowLabelWidth + 1 - Viewport.X,
|
||||
Y = newSelectedCodePoint / 16 * _rowHeight + 1 - Viewport.Y
|
||||
};
|
||||
|
||||
// Ensure the new cursor position is visible
|
||||
EnsureCursorIsVisible (newCursor);
|
||||
|
||||
_selected = newSelectedCodePoint;
|
||||
SetNeedsDraw ();
|
||||
SelectedCodePointChanged?.Invoke (this, new (SelectedCodePoint, null));
|
||||
}
|
||||
}
|
||||
|
||||
private void ScrollToMakeRowVisible (int row, int prevCursorY)
|
||||
private void EnsureCursorIsVisible (Point newCursor)
|
||||
{
|
||||
int height = Viewport.Height - 1; // Header
|
||||
int delta = row - (Viewport.Y + height);
|
||||
int scroll = Viewport.Height - (prevCursorY - delta);
|
||||
// Adjust vertical scrolling
|
||||
if (newCursor.Y < 1) // Header is at Y = 0
|
||||
{
|
||||
ScrollVertical (newCursor.Y - 1);
|
||||
}
|
||||
else if (newCursor.Y >= Viewport.Height)
|
||||
{
|
||||
ScrollVertical (newCursor.Y - Viewport.Height + 1);
|
||||
}
|
||||
|
||||
if (row - Viewport.Y < 0)
|
||||
_vScrollBar.ContentPosition = Viewport.Y;
|
||||
|
||||
// Adjust horizontal scrolling
|
||||
if (newCursor.X < RowLabelWidth + 1)
|
||||
{
|
||||
// Moving up.
|
||||
Viewport = Viewport with { Y = Viewport.Y + (row - Viewport.Y) };
|
||||
ScrollHorizontal (newCursor.X - (RowLabelWidth + 1));
|
||||
}
|
||||
else if (row - Viewport.Y >= height)
|
||||
else if (newCursor.X >= Viewport.Width)
|
||||
{
|
||||
// Moving down.
|
||||
Viewport = Viewport with { Y = Math.Min (Viewport.Y + scroll, GetContentSize ().Height - height ) };
|
||||
ScrollHorizontal (newCursor.X - Viewport.Width + 1);
|
||||
}
|
||||
_vScrollBar.ContentPosition = row;
|
||||
|
||||
_hScrollBar.ContentPosition = Viewport.X;
|
||||
}
|
||||
|
||||
private void ScrollToMakeColumnVisible (int col, int prevCursorX)
|
||||
{
|
||||
int width = Viewport.Width - RowLabelWidth;
|
||||
int delta = col - (Viewport.X + width);
|
||||
int scroll = Viewport.Width - (prevCursorX - delta);
|
||||
|
||||
if (col - Viewport.X < 0)
|
||||
{
|
||||
// Moving left.
|
||||
Viewport = Viewport with { X = Viewport.X + (col - Viewport.X) };
|
||||
_hScrollBar.ContentPosition = col;
|
||||
}
|
||||
else if (col - Viewport.X >= width)
|
||||
{
|
||||
// Moving right.
|
||||
Viewport = Viewport with { X = Math.Min (Viewport.X + scroll, GetContentSize ().Width - width) };
|
||||
_hScrollBar.ContentPosition = col;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool ShowGlyphWidths
|
||||
{
|
||||
get => _rowHeight == 2;
|
||||
@@ -997,7 +1000,7 @@ internal class CharMap : View, IDesignable
|
||||
document.RootElement,
|
||||
new
|
||||
JsonSerializerOptions
|
||||
{ WriteIndented = true }
|
||||
{ WriteIndented = true }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user