-
Notifications
You must be signed in to change notification settings - Fork 31
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
Add UI elements for textual filtering of tests #1166
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// *********************************************************************** | ||
// Copyright (c) Charlie Poole and TestCentric contributors. | ||
// Licensed under the MIT License. See LICENSE file in root directory. | ||
// *********************************************************************** | ||
|
||
using System.Drawing; | ||
using System.Windows.Forms; | ||
using System; | ||
|
||
namespace TestCentric.Gui.Controls | ||
{ | ||
/// <summary> | ||
/// This class is required to stretch a ToolStripTextBox control within a ToolStrip to fill the available space and to resize when the control resizes. | ||
/// The implementation is from the Microsoft Windows Forms documentation, but simplified to the current use case. | ||
/// "How to: Stretch a ToolStripTextBox to Fill the Remaining Width of a ToolStrip" | ||
/// https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/stretch-a-toolstriptextbox-to-fill-the-remaining-width-of-a-toolstrip-wf?view=netframeworkdesktop-4.8 | ||
/// </summary> | ||
internal class StretchToolStripTextBox : ToolStripTextBox | ||
{ | ||
public override Size GetPreferredSize(Size constrainingSize) | ||
{ | ||
// Get width of the owning ToolStrip | ||
int textBoxMargin = 2; | ||
Int32 width = Owner.DisplayRectangle.Width - textBoxMargin; | ||
|
||
// If the available width is less than the default width, use the default width | ||
if (width < DefaultSize.Width) width = DefaultSize.Width; | ||
|
||
// Retrieve the preferred size from the base class, but change the width to the calculated width. | ||
Size size = base.GetPreferredSize(constrainingSize); | ||
size.Width = width; | ||
return size; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// *********************************************************************** | ||
// Copyright (c) Charlie Poole and TestCentric contributors. | ||
// Licensed under the MIT License. See LICENSE file in root directory. | ||
// *********************************************************************** | ||
|
||
namespace TestCentric.Gui.Elements | ||
{ | ||
/// <summary> | ||
/// The IChanged interface represents a IViewElement. | ||
/// If the IViewElement changes, it will raise the Changed event. | ||
/// </summary> | ||
public interface IChanged : IViewElement | ||
{ | ||
/// <summary> | ||
/// Event raised when the element is changed by the user | ||
/// </summary> | ||
event CommandHandler Changed; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// *********************************************************************** | ||
// Copyright (c) Charlie Poole and TestCentric contributors. | ||
// Licensed under the MIT License. See LICENSE file in root directory. | ||
// *********************************************************************** | ||
|
||
|
||
using System; | ||
using System.Windows.Forms; | ||
|
||
namespace TestCentric.Gui.Elements | ||
{ | ||
/// <summary> | ||
/// This class implements the IChanged interface for a TextBox control. It provides this additional functionality: | ||
/// - show a PlaceHoder text if there's no text input | ||
/// - Invoke the Changed event as soon as no further input is made within a short period of time. | ||
/// </summary> | ||
public class TextBoxElement : IChanged | ||
{ | ||
private Timer _typingTimer; | ||
|
||
public event CommandHandler Changed; | ||
|
||
public TextBoxElement(Control textBox, string placeHolderText) | ||
{ | ||
TextBox = textBox; | ||
PlaceHolderText = placeHolderText; | ||
TextBox.TextChanged += OnTextChanged; | ||
|
||
TextBox.LostFocus += OnTextBoxLostFocus; | ||
TextBox.GotFocus += OnTextBoxGotFocus; | ||
|
||
// Call LostFocus to set initial text and color | ||
OnTextBoxLostFocus(null, EventArgs.Empty); | ||
} | ||
|
||
public bool Enabled | ||
{ | ||
get => TextBox.Enabled; | ||
set => TextBox.Enabled = value; | ||
} | ||
|
||
public bool Visible | ||
{ | ||
get => TextBox.Visible; | ||
set => TextBox.Visible = value; | ||
} | ||
|
||
public string Text | ||
{ | ||
get => TextBox.Text; | ||
set => TextBox.Text = value; | ||
} | ||
|
||
private string PlaceHolderText { get; set; } | ||
|
||
private Control TextBox { get; } | ||
|
||
private bool IsPlaceHolderTextShown { get; set; } | ||
|
||
public void InvokeIfRequired(MethodInvoker _delegate) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
private void OnTextBoxGotFocus(object sender, EventArgs e) | ||
{ | ||
// If the PlaceHolderText is shown, replace it with an empty text | ||
if (IsPlaceHolderTextShown) | ||
{ | ||
TextBox.Text = ""; | ||
TextBox.ForeColor = System.Drawing.Color.Black; | ||
IsPlaceHolderTextShown = false; | ||
} | ||
} | ||
|
||
private void OnTextBoxLostFocus(object sender, EventArgs e) | ||
{ | ||
// If there's no text input, show the PlaceHolderText instead | ||
string searchText = TextBox.Text; | ||
if (string.IsNullOrEmpty(searchText) && !string.IsNullOrEmpty(PlaceHolderText)) | ||
{ | ||
IsPlaceHolderTextShown = true; | ||
TextBox.Text = PlaceHolderText; | ||
TextBox.ForeColor = System.Drawing.Color.LightGray; | ||
} | ||
} | ||
|
||
private void OnTextChanged(object sender, EventArgs e) | ||
{ | ||
if (IsPlaceHolderTextShown) | ||
return; | ||
|
||
if (_typingTimer == null) | ||
{ | ||
_typingTimer = new Timer(); | ||
_typingTimer.Interval = 600; | ||
_typingTimer.Tick += TypingTimerTimeout; | ||
} | ||
|
||
_typingTimer.Stop(); | ||
_typingTimer.Start(); | ||
} | ||
|
||
private void TypingTimerTimeout(object sender, EventArgs e) | ||
{ | ||
var timer = sender as Timer; | ||
if (timer == null) | ||
return; | ||
|
||
// The timer must be stopped! | ||
timer.Stop(); | ||
if (Changed != null) | ||
Changed(); | ||
|
||
TextBox.Focus(); | ||
} | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the timeout strictly necessary? I'm fairly accustomed to controls that do nothing until I tab away or otherwise change focus. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This 'timeout' feature is definitely just a gimmick and not absolutely necessary. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ToolStripElement already implements many of the basic properties. Suggested name change is consistent with our naming of other tool strip elements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, you've convinced me 👍 !
I will rename this class to ToolStripTextBoxElement and derive it from base class ToolStripElement.