diff --git a/.gitignore b/.gitignore
index bdc3535f7..e2d7b7019 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,9 @@ TestResults
*.user
*.sln.docstates
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+
# Build results
[Dd]ebug/
[Rr]elease/
diff --git a/Binary/FastColoredTextBox.dll b/Binary/FastColoredTextBox.dll
index 1ba295cc9..d19482795 100644
Binary files a/Binary/FastColoredTextBox.dll and b/Binary/FastColoredTextBox.dll differ
diff --git a/Binary/FastColoredTextBox.xml b/Binary/FastColoredTextBox.xml
index 091404f54..f2d89f2f2 100644
--- a/Binary/FastColoredTextBox.xml
+++ b/Binary/FastColoredTextBox.xml
@@ -179,6 +179,41 @@
Tooltip
+
+
+ Make the menu fit to width of shown items.
+
+
+
+
+ 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.
+
+
+
+
+ Set to true to remove the padding for icons on the left of the menu
+
+
+
+
+ Set to true to use solid brush for selected item. Default is a linear gradient from SelectedColor to a transparent.
+
+
+
+
+ Set to true to show menu again after an item is selected.
+
+
+
+
+ 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.
+
+
+
+
+ The duration of tooltip showing in milliseconds. Set to 0 to show tooltip indefinitely.
+
+
Base class for bookmark collection
diff --git a/Binary/Tester.exe b/Binary/Tester.exe
index ec4f27a96..4d137af60 100644
Binary files a/Binary/Tester.exe and b/Binary/Tester.exe differ
diff --git a/FastColoredTextBox/AutocompleteMenu.cs b/FastColoredTextBox/AutocompleteMenu.cs
index 829783acf..a3c645235 100644
--- a/FastColoredTextBox/AutocompleteMenu.cs
+++ b/FastColoredTextBox/AutocompleteMenu.cs
@@ -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
@@ -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;
@@ -223,10 +225,60 @@ private int ItemHeight
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
internal bool AllowTabKey { get; set; }
+
+ ///
+ /// Make the menu fit to width of shown items.
+ ///
+ private bool _autoWidth;
+ public bool AutoWidth
+ {
+ get => _autoWidth;
+ set
+ {
+ _autoWidth = value;
+ MaximumSize = new Size(_autoWidth ? 1000 : Size.Width, MaximumSize.Height);
+ }
+ }
+
+ ///
+ /// 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.
+ ///
+ public int AutoWidthExtraPadding { get; set; } = 10;
+
+ ///
+ /// Set to true to remove the padding for icons on the left of the menu
+ ///
+ public bool NoSpacingForIcons { get; set; }
+ ///
+ /// Set to true to use solid brush for selected item. Default is a linear gradient from SelectedColor to a transparent.
+ ///
+ public bool UseSolidBrushForSelected { get; set; }
+ ///
+ /// Set to true to show menu again after an item is selected.
+ ///
+ public bool ReShowMenuAfterSelected { get; set; }
+ ///
+ /// 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.
+ ///
+ public bool DisableWrappingUpDownNavigation { get; set; }
public ImageList ImageList { get; set; }
internal int AppearInterval { get { return timer.Interval; } set { timer.Interval = value; } }
+ ///
+ /// The duration of tooltip showing in milliseconds. Set to 0 to show tooltip indefinitely.
+ ///
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; }
@@ -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)
@@ -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);
@@ -513,6 +579,8 @@ void AdjustScroll()
oldItemCount = visibleItems.Count;
}
+ private int biggestTextWidth;
+ private bool widthChanged;
protected override void OnPaint(PaintEventArgs e)
{
AdjustScroll();
@@ -523,7 +591,7 @@ 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;
@@ -531,26 +599,44 @@ protected override void OnPaint(PaintEventArgs e)
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;
}
}
@@ -610,6 +696,7 @@ internal virtual void OnSelecting()
}
Menu.Close();
+ if(ReShowMenuAfterSelected) ResetTimer(timer);
//
SelectedEventArgs args2 = new SelectedEventArgs()
{
@@ -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();
@@ -722,6 +819,8 @@ private void DoSelectedVisible()
AutoScrollMinSize += new Size(1, 0);
}
+ private AutocompleteItem toBeUsedInOnPaint;
+
private void SetToolTip(AutocompleteItem autocompleteItem)
{
var title = autocompleteItem.ToolTipTitle;
@@ -729,8 +828,8 @@ private void SetToolTip(AutocompleteItem autocompleteItem)
if (string.IsNullOrEmpty(title))
{
- toolTip.ToolTipTitle = null;
- toolTip.SetToolTip(this, null);
+ toolTip.Hide(Parent ?? this);
+ toBeUsedInOnPaint = null;
return;
}
@@ -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);
}
}
}
diff --git a/FastColoredTextBox/FastColoredTextBox.cs b/FastColoredTextBox/FastColoredTextBox.cs
index 9af2ff3ca..88fb68589 100644
--- a/FastColoredTextBox/FastColoredTextBox.cs
+++ b/FastColoredTextBox/FastColoredTextBox.cs
@@ -125,7 +125,9 @@ public partial class FastColoredTextBox : UserControl, ISupportInitialize
private int reservedCountOfLineNumberChars = 1;
private int zoom = 100;
private Size localAutoScrollMinSize;
-
+ private bool mouseIsWholeWordSelection;
+ private Range mouseIsWholeWordSelectionBaseRange;
+
///
/// Constructor
///
@@ -5481,6 +5483,7 @@ protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
mouseIsDrag = false;
+ mouseIsWholeWordSelection = false;
mouseIsDragDrop = false;
draggedRange = null;
}
@@ -5505,7 +5508,8 @@ protected override void OnMouseDown(MouseEventArgs e)
{
DeactivateMiddleClickScrollingMode();
mouseIsDrag = false;
- if(e.Button == System.Windows.Forms.MouseButtons.Middle)
+ mouseIsWholeWordSelection = false;
+ if (e.Button == System.Windows.Forms.MouseButtons.Middle)
RestoreScrollsAfterMiddleClickScrollingMode();
return;
}
@@ -5522,6 +5526,7 @@ protected override void OnMouseDown(MouseEventArgs e)
if (marker != null)
{
mouseIsDrag = false;
+ mouseIsWholeWordSelection = false;
mouseIsDragDrop = false;
draggedRange = null;
OnMarkerClick(e, marker);
@@ -5539,11 +5544,11 @@ protected override void OnMouseDown(MouseEventArgs e)
if (e.Clicks == 2)
{
- mouseIsDrag = false;
mouseIsDragDrop = false;
- draggedRange = null;
+ mouseIsWholeWordSelection = true;
SelectWord(p);
+ mouseIsWholeWordSelectionBaseRange = Selection.Clone();
return;
}
@@ -5553,6 +5558,7 @@ protected override void OnMouseDown(MouseEventArgs e)
{
mouseIsDragDrop = true;
mouseIsDrag = false;
+ mouseIsWholeWordSelection = false;
}
}
else
@@ -5819,19 +5825,43 @@ protected override void OnMouseMove(MouseEventArgs e)
}
else if (place != Selection.Start)
{
- Place oldEnd = Selection.End;
- Selection.BeginUpdate();
- if (Selection.ColumnSelectionMode)
+ if (mouseIsWholeWordSelection)
{
- Selection.Start = place;
- Selection.ColumnSelectionMode = true;
+ Selection.BeginUpdate();
+ var oldSelection = Selection.Clone();
+ SelectWord(place);
+
+ if (Selection.End >= mouseIsWholeWordSelectionBaseRange.End)
+ {
+ Selection.Start = (mouseIsWholeWordSelectionBaseRange.Start > Selection.Start) ? mouseIsWholeWordSelectionBaseRange.Start : Selection.Start;
+ Selection.End = mouseIsWholeWordSelectionBaseRange.End;
+ }
+ else if (Selection.Start < mouseIsWholeWordSelectionBaseRange.End)
+ {
+ Selection.Start = new Place(Selection.End.iChar, Selection.End.iLine);
+ Selection.End = mouseIsWholeWordSelectionBaseRange.Start;
+ }
+
+ Selection.EndUpdate();
+ DoCaretVisible();
+ Invalidate();
}
else
- Selection.Start = place;
- Selection.End = oldEnd;
- Selection.EndUpdate();
- DoCaretVisible();
- Invalidate();
+ {
+ Place oldEnd = Selection.End;
+ Selection.BeginUpdate();
+ if (Selection.ColumnSelectionMode)
+ {
+ Selection.Start = place;
+ Selection.ColumnSelectionMode = true;
+ }
+ else
+ Selection.Start = place;
+ Selection.End = oldEnd;
+ Selection.EndUpdate();
+ DoCaretVisible();
+ Invalidate();
+ }
return;
}
}
diff --git a/FastColoredTextBox/Range.cs b/FastColoredTextBox/Range.cs
index 2faabd9f8..aba431aef 100644
--- a/FastColoredTextBox/Range.cs
+++ b/FastColoredTextBox/Range.cs
@@ -816,7 +816,8 @@ public void SetStyle(StyleIndex styleIndex)
for (int x = fromX; x <= toX; x++)
{
Char c = tb[y][x];
- c.style |= styleIndex;
+ if(tb.AllowSeveralTextStyleDrawing) c.style |= styleIndex;
+ else c.style = styleIndex;
tb[y][x] = c;
}
}
diff --git a/README.md b/README.md
index b68b1f2a3..ba7eb61d2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,19 @@
-FastColoredTextBox
+FastColoredTextBox - FIXED
==================
+This fork fixes a lot of bugs in the original repo, and adds some nice-to-have features. This was necessitated by my use of this component in [Regexer](https://github.com/PeteJobi/Regexer).
+
+- Double-click + drag can now select multiple words, just like it works in notepad. Thanks to this [stackoverflow answer](https://stackoverflow.com/a/25708621/5920922).
+- If AllowSeveralTextStyleDrawing is true, applying a style to characters will stack over whatever style was there before (as intended by original author), but if false, applying a style will override whatever style was there before. This fixes styling bugs I encountered.
+- The auto-complete menu can now wrap around when navigating i.e if you press down when you're on the last item, you go to the first item. If you press up when you're on the first item, you go to last item.
+- You can now set ToolTipDuration to 0 to show a tooltip indefinitely.
+- You can choose to use a solid brush for the selected auto-complete item instead of the default gradient brush.
+- You can remove the spacing for icons in the auto-complete menu by setting NoSpacingForIcons to true.
+- If you want the auto-complete menu to show up again automatically after the user selects an item, set ReShowMenuAfterSelected to true.
+- Fixed bug where tooltip shows up for items that don't have tooltips specified.
+- If AutoWidth is set to true, the auto-complete menu will automatically resize its width to fit the items. Use AutoWidthExtraPadding to put some spacing between the right edge of the menu and the widest item. If any tooltip is shown while the menu resizes, it is reshown to adjust its position.
+- Fixed bug with MaxToolTipSize. Before now, the MaxToolTipSize actually sets the width and height of the tooltip, even when the tooltip size is smaller than MaxToolTipSize. Now, MaxToolTipSize only limits the size of the tooltip when it would otherwise exceed it, and the tooltip text wraps around as expected.
+
Fast Colored TextBox is text editor component for .NET.
Allows you to create custom text editor with syntax highlighting.
It works well with small, medium, large and very-very large files.