Skip to content

Commit

Permalink
Add TextArea.BorderType, ScrollToTop/Bottom/Range, and TextLength
Browse files Browse the repository at this point in the history
  • Loading branch information
cwensley committed Dec 1, 2023
1 parent 1c59032 commit 1e57432
Show file tree
Hide file tree
Showing 9 changed files with 343 additions and 29 deletions.
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

0 comments on commit 1e57432

Please sign in to comment.