Skip to content
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 TextArea.Border, ScrollToTop/Bottom/Range, and TextLength #2587

Merged
merged 1 commit into from
Dec 1, 2023
Merged
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
52 changes: 49 additions & 3 deletions src/Eto.Gtk/Forms/Controls/TextAreaHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class TextAreaHandler<TControl, TWidget, TCallback> : GtkControl<TControl
int suppressSelectionAndTextChanged;
readonly Gtk.ScrolledWindow scroll;
Gtk.TextTag tag;
BorderType border = BorderType.Bezel;

public override Gtk.Widget ContainerControl
{
Expand Down Expand Up @@ -332,13 +333,58 @@ public bool SpellCheck

public TextReplacements TextReplacements
{
get { return TextReplacements.None; }
get => TextReplacements.None;
set { }
}

public TextReplacements SupportedTextReplacements
public TextReplacements SupportedTextReplacements => TextReplacements.None;

public virtual BorderType Border
{
get { return TextReplacements.None; }
get => border;
set
{
border = value;
switch (border)
{
case BorderType.Bezel:
scroll.ShadowType = Gtk.ShadowType.In;
break;
case BorderType.Line:
scroll.ShadowType = Gtk.ShadowType.In;
break;
case BorderType.None:
scroll.ShadowType = Gtk.ShadowType.None;
break;
default:
throw new NotSupportedException();
}
}
}

public virtual int TextLength => Control.Buffer.CharCount;

public virtual void ScrollTo(Range<int> range)
{
var iter = Control.Buffer.GetIterAtOffset(range.Start + range.Length());
var mark = Control.Buffer.CreateMark(null, iter, false);
Control.ScrollToMark(mark, 0, false, 0, 0);
}

public virtual void ScrollToEnd()
{
var end = Control.Buffer.EndIter;
var mark = Control.Buffer.CreateMark(null, end, false);
Control.ScrollToMark(mark, 0, false, 0, 0);
}

public virtual void ScrollToStart()
{
var end = Control.Buffer.StartIter;
var mark = Control.Buffer.CreateMark(null, end, false);
Control.ScrollToMark(mark, 0, false, 0, 0);
}


}
}
28 changes: 20 additions & 8 deletions src/Eto.Mac/Forms/Controls/TextAreaHandler.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using Eto.Mac.Drawing;
using Range = Eto.Forms.Range;

namespace Eto.Mac.Forms.Controls
{
public class TextAreaHandler : TextAreaHandler<TextArea, TextArea.ICallback>, TextArea.IHandler
{
}
internal static readonly IntPtr selString = Selector.GetHandle("string");
internal static readonly IntPtr selLength = Selector.GetHandle("length"); }

public interface ITextAreaHandler
{
Expand Down Expand Up @@ -258,9 +260,9 @@ public Color TextColor
}
}
}

static readonly object DisabledBackgroundColor_Key = new object();

public virtual Color DisabledBackgroundColor
{
get => Widget.Properties.Get<Color?>(DisabledBackgroundColor_Key) ?? NSColor.WindowBackground.ToEto();
Expand Down Expand Up @@ -380,11 +382,7 @@ public bool AcceptsReturn

public void Append(string text, bool scrollToCursor)
{
// get NSString object so we don't have to marshal the entire string to get its length
var stringValuePtr = Messaging.IntPtr_objc_msgSend(Control.Handle, selGetString);
var str = Runtime.GetNSObject<NSString>(stringValuePtr);

var range = new NSRange(str != null ? str.Length : 0, 0);
var range = new NSRange(TextLength, 0);
Control.Replace(range, text);
range.Location += text.Length;
Control.SetSelectedRange(range);
Expand Down Expand Up @@ -453,5 +451,19 @@ public TextReplacements SupportedTextReplacements
{
get { return TextReplacements.Quote | TextReplacements.Text | TextReplacements.Dash | TextReplacements.Spelling; }
}

public BorderType Border
{
get => Scroll.BorderType.ToEto();
set => Scroll.BorderType = value.ToNS();
}

public int TextLength => (int)Control.TextStorage.Length;

public void ScrollTo(Range<int> range) => Control.ScrollRangeToVisible(range.ToNS());

public void ScrollToStart() => ScrollTo(new Range<int>(0));

public void ScrollToEnd() => ScrollTo(Range.FromLength(TextLength, 0));
}
}
47 changes: 46 additions & 1 deletion src/Eto.WinForms/Forms/Controls/TextAreaHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class TextAreaHandler<TWidget, TCallback> : WindowsControl<EtoRichTextBox
swf.TableLayoutPanel container;

internal override bool SetFontTwiceForSomeReason => true;

public static Size DefaultMinimumSize = new Size(100, 60);

public override Size? GetDefaultSize(Size availableSize)
Expand Down Expand Up @@ -245,5 +245,50 @@ public TextReplacements SupportedTextReplacements
{
get { return TextReplacements.None; }
}

public BorderType Border
{
get => container.BorderStyle.ToEto();
set => container.BorderStyle = value.ToSWF();
}

public int TextLength => Control.TextLength;

public void ScrollTo(Range<int> range)
{
var pos = Control.GetPositionFromCharIndex(range.End);
sd.Point scrollPosition = sd.Point.Empty;
Win32.SendMessage(Control.Handle, Win32.WM.EM_GETSCROLLPOS, IntPtr.Zero, ref scrollPosition);

var si = new Win32.SCROLLINFO();
si.cbSize = Marshal.SizeOf(si);
si.fMask = (int)Win32.ScrollInfoMask.SIF_ALL;
Win32.GetScrollInfo(Control.Handle, (int)Win32.SBOrientation.SB_VERT, ref si);

if (si.nPage > 0)
scrollPosition.Y = Math.Min(si.nMax - si.nPage, Math.Max(si.nMin, scrollPosition.Y + pos.Y));

Win32.GetScrollInfo(Control.Handle, (int)Win32.SBOrientation.SB_HORZ, ref si);

// only scroll X if not in view already
if (si.nPage > 0 && (pos.X < si.nPos || pos.X > si.nPos + si.nPage))
scrollPosition.X = Math.Min(si.nMax - si.nPage, Math.Max(si.nMin, scrollPosition.X + pos.X));

Win32.SendMessage(Control.Handle, Win32.WM.EM_SETSCROLLPOS, IntPtr.Zero, ref scrollPosition);
}

public void ScrollToStart()
{
Win32.SendMessage(Control.Handle, Win32.WM.VSCROLL, (IntPtr)Win32.SB.TOP, IntPtr.Zero);
Win32.SendMessage(Control.Handle, Win32.WM.HSCROLL, (IntPtr)Win32.SB.LEFT, IntPtr.Zero);
}

public void ScrollToEnd()
{
Win32.SendMessage(Control.Handle, Win32.WM.VSCROLL, (IntPtr)Win32.SB.BOTTOM, IntPtr.Zero);
Win32.SendMessage(Control.Handle, Win32.WM.HSCROLL, (IntPtr)Win32.SB.LEFT, IntPtr.Zero);
}


}
}
77 changes: 67 additions & 10 deletions src/Eto.WinForms/Win32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@ public enum WS_EX : uint
NOACTIVATE = 0x08000000
}

public enum SB
{
THUMBTRACK = 5,
TOP = 6,
LEFT = 6,
BOTTOM = 7,
RIGHT = 7
}

public enum WM
{
SETREDRAW = 0xB,
Expand Down Expand Up @@ -180,9 +189,14 @@ public enum WM
NCCREATE = 0x0081,
NCLBUTTONDOWN = 0x00A1,
PRINT = 0x0317,
SHOWWINDOW = 0x00000018
SHOWWINDOW = 0x00000018,
HSCROLL = 0x114,
VSCROLL = 0x115,
USER = 0x400,
EM_GETSCROLLPOS = USER + 221,
EM_SETSCROLLPOS = USER + 222,
}

public enum VK : long
{
SHIFT = 0x10,
Expand Down Expand Up @@ -332,6 +346,9 @@ public static swf.MouseButtons GetMouseButtonWParam(IntPtr wParam)
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, WM msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, WM wMsg, IntPtr wParam, ref sd.Point lParam);


[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool PeekMessage(ref swf.Message wMsg, IntPtr hwnd, int msgMin, int msgMax, int remove);
Expand Down Expand Up @@ -411,17 +428,17 @@ public static string GetWindowText(IntPtr hwnd)
}

// for tray indicator

public enum WH
{
KEYBOARD = 2,
KEYBOARD_LL = 13,
MOUSE_LL = 14
}

public static IntPtr SetHook(WH hookId, HookProc proc)
{

public static IntPtr SetHook(WH hookId, HookProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
Expand All @@ -439,7 +456,7 @@ public static IntPtr SetHook(WH hookId, HookProc proc)
public static extern IntPtr SetWindowsHookEx(IntPtr hookId, HookProc function, IntPtr instance, int threadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hookId);

[DllImportAttribute("user32.dll")]
Expand Down Expand Up @@ -542,19 +559,19 @@ public static IntPtr GetThreadFocusWindow(uint? threadId = null)
public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
public static extern bool EnableMenuItem(IntPtr hMenu, SC uIDEnableItem, MF uEnable);

[Flags]
public enum MF : uint
{
BYCOMMAND = 0x00000000,
GRAYED = 0x00000001
}

public enum SC : uint
{
CLOSE = 0xF060
}

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GlobalLock(IntPtr handle);

Expand All @@ -563,5 +580,45 @@ public enum SC : uint

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GlobalSize(IntPtr handle);


public enum SBB
{
HORZ = 0,
VERT = 1
}

public enum ScrollInfoMask : uint
{
SIF_RANGE = 0x1,
SIF_PAGE = 0x2,
SIF_POS = 0x4,
SIF_DISABLENOSCROLL = 0x8,
SIF_TRACKPOS = 0x10,
SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS),
}
public enum SBOrientation : int
{
SB_HORZ = 0x0,
SB_VERT = 0x1,
SB_CTL = 0x2,
SB_BOTH = 0x3
}

[Serializable, StructLayout(LayoutKind.Sequential)]
public struct SCROLLINFO
{
public int cbSize; // (uint) int is because of Marshal.SizeOf
public uint fMask;
public int nMin;
public int nMax;
public int nPage;
public int nPos;
public int nTrackPos;
}

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);
}
}
11 changes: 11 additions & 0 deletions src/Eto.Wpf/Forms/Controls/RichTextAreaHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,17 @@ public override TextAlignment TextAlignment
ContentRange.ApplyPropertyValue(swd.Block.TextAlignmentProperty, value.ToWpfTextAlignment());
}
}

public override void ScrollTo(Range<int> range)
{
var textRange = GetRange(range);
var rect = textRange.End.GetCharacterRect(swd.LogicalDirection.Backward);
Control.ScrollToVerticalOffset(rect.Top);
Control.ScrollToHorizontalOffset(rect.Left);
}

public override int TextLength => ContentRange.GetLength();

}

static class FlowDocumentExtensions
Expand Down
Loading
Loading