#include using namespace Upp; struct MyApp : TopWindow { LineEdit editor; ArrayCtrl list; Splitter splitter; int dosel = 0; MyApp(); }; MyApp::MyApp() { Add(splitter.SizePos()); splitter.Horz(list, editor); list.AddRowNumColumn().ConvertBy([=](const Value& v)->Value { int ii = v; if(ii >= editor.GetLineCount()) return Null; return AsString(ii) << " " << FormatIntRoman(ii, true); }); list.NoHeader().NoGrid().HideSb(); list.NoWantFocus(); String text; for(int i = 0; i < 1000; i++) text << "Line " << AsString(i) << "\n"; editor <<= text; int cy = editor.GetFontSize().cy; list.SetLineCy(cy); editor.WhenAction = editor.WhenScroll = [=] { list.SetVirtualCount(editor.GetLineCount() + 2); // unfortunately, we need 2 more lines to cover LineEdit end of text list.ScrollTo(editor.GetScrollPos().y * cy); }; editor.WhenSel = [=] { if(dosel) // avoid infinite recursion return; dosel++; list.SetCursor(editor.GetCursorLine()); list.WhenAction(); dosel--; }; list.WhenScroll = [=] { editor.SetScrollPos(Point(0, list.GetScroll() / cy)); }; list.WhenSel = [=] { if(dosel) // avoid infinite recursion return; dosel++; int i = list.GetCursor(); if(i >= 0 && i <= editor.GetLength()) { editor.SetCursor(editor.GetPos(i)); editor.WhenAction(); } dosel--; }; editor.WhenAction(); // set initial scroll position in the list editor.WhenSel(); // set initial cursor position in the list } GUI_APP_MAIN { MyApp().Run(); }