Skip to content

Commit

Permalink
Merge pull request #1446 from glopesdev/bufferedvisualizers
Browse files Browse the repository at this point in the history
Refactor text visualizer to use buffered updates
  • Loading branch information
glopesdev authored Jul 2, 2023
2 parents fbd235e + cab0769 commit 9d92492
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
using System;
using System.Collections.Generic;
using System.Reactive;
using System.Reactive.Linq;
using System.Windows.Forms;

namespace Bonsai.Design.Visualizers
namespace Bonsai.Design
{
/// <summary>
/// Provides an abstract base class for type visualizers with an update
/// frequency potentially much higher than the screen refresh rate.
/// </summary>
public abstract class BufferedVisualizer : DialogTypeVisualizer
{
const int TargetInterval = 1000 / 50;

internal BufferedVisualizer()
{
}
/// <summary>
/// Gets or sets the target interval, in milliseconds, between visualizer updates.
/// </summary>
protected virtual int TargetInterval => 1000 / 50;

/// <inheritdoc/>
public override IObservable<object> Visualize(IObservable<IObservable<object>> source, IServiceProvider provider)
Expand All @@ -39,17 +40,26 @@ public override IObservable<object> Visualize(IObservable<IObservable<object>> s
return mergedSource
.Timestamp(HighResolutionScheduler.Default)
.Buffer(() => timerTick)
.Do(buffer =>
{
foreach (var timestamped in buffer)
{
var time = timestamped.Timestamp.LocalDateTime;
Show(time, timestamped.Value);
}
}).Finally(timer.Stop);
.Do(ShowBuffer).Finally(timer.Stop);
});
}

/// <summary>
/// Updates the type visualizer with a new buffer of timestamped values.
/// </summary>
/// <param name="values">
/// A buffer of timestamped values where each timestamp indicates the
/// time at which the value was received.
/// </param>
protected virtual void ShowBuffer(IList<Timestamped<object>> values)
{
foreach (var timestamped in values)
{
var time = timestamped.Timestamp.LocalDateTime;
Show(time, timestamped.Value);
}
}

/// <summary>
/// Updates the type visualizer to display a buffered value object
/// received at the specified time.
Expand Down
27 changes: 20 additions & 7 deletions Bonsai.Design/ObjectTextVisualizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Bonsai;
using Bonsai.Design;
using System.Drawing;
using System.Reactive;

[assembly: TypeVisualizer(typeof(ObjectTextVisualizer), Target = typeof(object))]

Expand All @@ -12,16 +13,30 @@ namespace Bonsai.Design
/// <summary>
/// Provides a type visualizer for displaying any object type as text.
/// </summary>
public class ObjectTextVisualizer : DialogTypeVisualizer
public class ObjectTextVisualizer : BufferedVisualizer
{
const int AutoScaleHeight = 13;
const float DefaultDpi = 96f;

TextBox textBox;
RichTextBox textBox;
UserControl textPanel;
Queue<string> buffer;
int bufferSize;

/// <inheritdoc/>
protected override int TargetInterval => 1000 / 30;

/// <inheritdoc/>
protected override void ShowBuffer(IList<Timestamped<object>> values)
{
if (values.Count > 0)
{
base.ShowBuffer(values);
textBox.Text = string.Join(Environment.NewLine, buffer);
textPanel.Invalidate();
}
}

/// <inheritdoc/>
public override void Show(object value)
{
Expand All @@ -31,18 +46,17 @@ public override void Show(object value)
{
buffer.Dequeue();
}
textBox.Text = string.Join(Environment.NewLine, buffer);
}

/// <inheritdoc/>
public override void Load(IServiceProvider provider)
{
buffer = new Queue<string>();
textBox = new TextBox { Dock = DockStyle.Fill };
textBox = new RichTextBox { Dock = DockStyle.Fill };
textBox.ReadOnly = true;
textBox.Multiline = true;
textBox.WordWrap = false;
textBox.TextChanged += (sender, e) => textPanel.Invalidate();
textBox.ScrollBars = RichTextBoxScrollBars.Horizontal;

textPanel = new UserControl();
textPanel.SuspendLayout();
Expand All @@ -66,9 +80,8 @@ void textPanel_Paint(object sender, PaintEventArgs e)
var lineHeight = AutoScaleHeight * e.Graphics.DpiY / DefaultDpi;
bufferSize = (int)((textBox.ClientSize.Height - 2) / lineHeight);
var textSize = TextRenderer.MeasureText(textBox.Text, textBox.Font);
if (textBox.ScrollBars == ScrollBars.None && textBox.ClientSize.Width < textSize.Width)
if (textBox.ClientSize.Width < textSize.Width)
{
textBox.ScrollBars = ScrollBars.Horizontal;
var offset = 2 * lineHeight + SystemInformation.HorizontalScrollBarHeight - textPanel.Height;
if (offset > 0)
{
Expand Down

0 comments on commit 9d92492

Please sign in to comment.