Skip to content
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ TestResults
*.user
*.sln.docstates

# Visual Studio 2015/2017 cache/options directory
.vs/

# Build results
[Dd]ebug/
[Rr]elease/
Expand Down
Binary file modified Binary/FastColoredTextBox.dll
Binary file not shown.
35 changes: 35 additions & 0 deletions Binary/FastColoredTextBox.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified Binary/Tester.exe
Binary file not shown.
142 changes: 122 additions & 20 deletions FastColoredTextBox/AutocompleteMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.Drawing;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

namespace FastColoredTextBoxNS
Expand Down Expand Up @@ -79,7 +81,7 @@ public AutocompleteMenu(FastColoredTextBox tb)
{
// create a new popup and add the list view to it
AutoClose = false;
AutoSize = false;
AutoSize = true;
Margin = Padding.Empty;
Padding = Padding.Empty;
BackColor = Color.White;
Expand Down Expand Up @@ -223,10 +225,60 @@ private int ItemHeight
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

internal bool AllowTabKey { get; set; }

/// <summary>
/// Make the menu fit to width of shown items.
/// </summary>
private bool _autoWidth;
public bool AutoWidth
{
get => _autoWidth;
set
{
_autoWidth = value;
MaximumSize = new Size(_autoWidth ? 1000 : Size.Width, MaximumSize.Height);
}
}

/// <summary>
/// If AutoWidth is true, this property specifies extra padding on the right of menu items. Default is 10. Note: AutoWidth should be true to use this property.
/// </summary>
public int AutoWidthExtraPadding { get; set; } = 10;

/// <summary>
/// Set to true to remove the padding for icons on the left of the menu
/// </summary>
public bool NoSpacingForIcons { get; set; }
/// <summary>
/// Set to true to use solid brush for selected item. Default is a linear gradient from SelectedColor to a transparent.
/// </summary>
public bool UseSolidBrushForSelected { get; set; }
/// <summary>
/// Set to true to show menu again after an item is selected.
/// </summary>
public bool ReShowMenuAfterSelected { get; set; }
/// <summary>
/// Set to false to disable wrapping up/down navigation. If false, user can't navigate from last item to first and back. Default is true.
/// </summary>
public bool DisableWrappingUpDownNavigation { get; set; }
public ImageList ImageList { get; set; }
internal int AppearInterval { get { return timer.Interval; } set { timer.Interval = value; } }
/// <summary>
/// The duration of tooltip showing in milliseconds. Set to 0 to show tooltip indefinitely.
/// </summary>
internal int ToolTipDuration { get; set; }
internal Size MaxToolTipSize { get; set; }

private Size maxToolTipSize;
internal Size MaxToolTipSize
{
get => maxToolTipSize;
set
{
maxToolTipSize = value;
SetTooltipMaxWidth();
}
}

internal bool AlwaysShowTooltip
{
get { return toolTip.ShowAlways; }
Expand Down Expand Up @@ -309,10 +361,23 @@ internal AutocompleteListView(FastColoredTextBox tb)
};
}

private const uint TTM_SETMAXTIPWIDTH = 0x418;
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hwnd, uint msg,
int wParam, int lParam);
private void SetTooltipMaxWidth()
{
var o = typeof(ToolTip).InvokeMember("Handle",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,
null, toolTip, null);
var hwnd = (IntPtr)o;
SendMessage(hwnd, TTM_SETMAXTIPWIDTH, 0, MaxToolTipSize.Width);
}

private void ToolTip_Popup(object sender, PopupEventArgs e)
{
if (MaxToolTipSize.Height > 0 && MaxToolTipSize.Width > 0)
e.ToolTipSize = MaxToolTipSize;
if (MaxToolTipSize.Height > 0)
e.ToolTipSize = new Size(e.ToolTipSize.Width, Math.Min(e.ToolTipSize.Height, MaxToolTipSize.Height));
}

protected override void Dispose(bool disposing)
Expand Down Expand Up @@ -387,6 +452,7 @@ internal void DoAutocomplete(bool forced)
visibleItems.Clear();
FocussedItemIndex = 0;
VerticalScroll.Value = 0;
biggestTextWidth = 0;
//some magic for update scrolls
AutoScrollMinSize -= new Size(1, 0);
AutoScrollMinSize += new Size(1, 0);
Expand Down Expand Up @@ -513,6 +579,8 @@ void AdjustScroll()
oldItemCount = visibleItems.Count;
}

private int biggestTextWidth;
private bool widthChanged;
protected override void OnPaint(PaintEventArgs e)
{
AdjustScroll();
Expand All @@ -523,34 +591,52 @@ protected override void OnPaint(PaintEventArgs e)
startI = Math.Max(startI, 0);
finishI = Math.Min(finishI, visibleItems.Count);
int y = 0;
int leftPadding = 18;
int leftPadding = NoSpacingForIcons ? 0 : 18;
for (int i = startI; i < finishI; i++)
{
y = i * itemHeight - VerticalScroll.Value;

var item = visibleItems[i];

if(item.BackColor != Color.Transparent)
using (var brush = new SolidBrush(item.BackColor))
e.Graphics.FillRectangle(brush, 1, y, ClientSize.Width - 1 - 1, itemHeight - 1);
using (var brush = new SolidBrush(item.BackColor))
e.Graphics.FillRectangle(brush, 1, y, ClientSize.Width - 1 - 1, itemHeight - 1);

if (ImageList != null && visibleItems[i].ImageIndex >= 0)
e.Graphics.DrawImage(ImageList.Images[item.ImageIndex], 1, y);

if (i == FocussedItemIndex)
using (var selectedBrush = new LinearGradientBrush(new Point(0, y - 3), new Point(0, y + itemHeight), Color.Transparent, SelectedColor))
using (var pen = new Pen(SelectedColor))
{
e.Graphics.FillRectangle(selectedBrush, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1);
e.Graphics.DrawRectangle(pen, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1);
}
using (var selectedBrush = UseSolidBrushForSelected ? (Brush)new SolidBrush(SelectedColor)
: new LinearGradientBrush(new Point(0, y - 3), new Point(0, y + itemHeight), Color.Transparent, SelectedColor))
using (var pen = new Pen(SelectedColor))
{
e.Graphics.FillRectangle(selectedBrush, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1);
e.Graphics.DrawRectangle(pen, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1);
}

if (i == hoveredItemIndex)
using(var pen = new Pen(HoveredColor))
e.Graphics.DrawRectangle(pen, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1);
using(var pen = new Pen(HoveredColor))
e.Graphics.DrawRectangle(pen, leftPadding, y, ClientSize.Width - 1 - leftPadding, itemHeight - 1);

using (var brush = new SolidBrush(item.ForeColor != Color.Transparent ? item.ForeColor : ForeColor))
e.Graphics.DrawString(item.ToString(), Font, brush, leftPadding, y);

if (!AutoWidth) continue;
var textSize = e.Graphics.MeasureString(item.ToString(), Font, new SizeF(500, 500));
if ((int)textSize.Width > biggestTextWidth)
{
biggestTextWidth = (int)textSize.Width;
widthChanged = true;
}
}

if (!widthChanged) return;
widthChanged = false;
Width = leftPadding + biggestTextWidth + AutoWidthExtraPadding + (VScroll ? SystemInformation.VerticalScrollBarWidth : 0);
if(toBeUsedInOnPaint != null)
{
SetToolTip(toBeUsedInOnPaint); //Adjust tooltip position after width change
toBeUsedInOnPaint = null;
}
}

Expand Down Expand Up @@ -610,6 +696,7 @@ internal virtual void OnSelecting()
}

Menu.Close();
if(ReShowMenuAfterSelected) ResetTimer(timer);
//
SelectedEventArgs args2 = new SelectedEventArgs()
{
Expand Down Expand Up @@ -701,7 +788,17 @@ private bool ProcessKey(Keys keyData, Keys keyModifiers)

public void SelectNext(int shift)
{
FocussedItemIndex = Math.Max(0, Math.Min(FocussedItemIndex + shift, visibleItems.Count - 1));
if (DisableWrappingUpDownNavigation)
{
FocussedItemIndex = Math.Max(0, Math.Min(FocussedItemIndex + shift, visibleItems.Count - 1));
}
else
{
var newIndex = FocussedItemIndex + shift;
if (newIndex < 0) newIndex = visibleItems.Count - 1;
else if (newIndex >= visibleItems.Count) newIndex = 0;
FocussedItemIndex = newIndex;
}
DoSelectedVisible();
//
Invalidate();
Expand All @@ -722,15 +819,17 @@ private void DoSelectedVisible()
AutoScrollMinSize += new Size(1, 0);
}

private AutocompleteItem toBeUsedInOnPaint;

private void SetToolTip(AutocompleteItem autocompleteItem)
{
var title = autocompleteItem.ToolTipTitle;
var text = autocompleteItem.ToolTipText;

if (string.IsNullOrEmpty(title))
{
toolTip.ToolTipTitle = null;
toolTip.SetToolTip(this, null);
toolTip.Hide(Parent ?? this);
toBeUsedInOnPaint = null;
return;
}

Expand All @@ -743,16 +842,19 @@ private void SetToolTip(AutocompleteItem autocompleteItem)
location = new Point(Right + 5, 0);
else
location = new Point(Left - 105 - MaximumSize.Width, 0);
toBeUsedInOnPaint = autocompleteItem;

if (string.IsNullOrEmpty(text))
{
toolTip.ToolTipTitle = null;
toolTip.Show(title, window, location.X, location.Y, ToolTipDuration);
if(ToolTipDuration > 0) toolTip.Show(title, window, location.X, location.Y, ToolTipDuration);
else toolTip.Show(title, window, location.X, location.Y);
}
else
{
toolTip.ToolTipTitle = title;
toolTip.Show(text, window, location.X, location.Y, ToolTipDuration);
if(ToolTipDuration > 0) toolTip.Show(text, window, location.X, location.Y, ToolTipDuration);
else toolTip.Show(text, window, location.X, location.Y);
}
}
}
Expand Down
Loading