The bottleneck is the fact that Pane
'cares' about full content even when only the fraction is needed. We need Pane
that fits our needs better.
The solution is based on a beta version of VerticalScrollbar
and ListPane
, if you find it hard to customize, let me know about options it should take, syntax etc.
It was only tested on Win7.
Let me know what changes you;d like to see in a polished version.
VerticalScrollbar // ClearAll ;
VerticalScrollbar // Options = {
"PageSize" -> .2
, ImageSize -> Automatic
};
VerticalScrollbar[Dynamic[scrollPosition_], OptionsPattern[] ]:=With[
{ pageSize = OptionValue["PageSize"]
, MPY := MousePosition[{"GraphicsScaled", Graphics}, {0,0}][[2]]
, thumbCol = GrayLevel @ .9
, thumbColActive = GrayLevel @ .8
, scrollHeight = .2
, imageSize = OptionValue[ImageSize] /. Automatic -> {15, Full}
}
, DynamicModule[
{
showScrollbar,
scrollRawPosition = 1 - (scrollPosition + scrollHeight),
mousePositionStart,
scrollRawPositionOffset = 0,
clipSRPos = Function[pos, Clip[pos, {0 , 1 - scrollHeight }]],
col = GrayLevel[.9]
}
,
Module[
{pane, scrollbar}
, scrollbar = Graphics[
DynamicNamespace @ { EdgeForm@Black, Dynamic@If[CurrentValue["MouseOver"], thumbColActive, thumbCol]
, Rectangle[{0, Dynamic[scrollRawPosition]}, {1, Dynamic[scrollRawPosition + scrollHeight]}, BoxID -> "thumb"]
, Black, Inset["=", DynamicLocation["thumb", None, Center]]
}
, ImageSize -> imageSize
, PlotRange -> {{0,1}, {0,1}}
, PlotRangePadding -> {2. / 15, 2./200}
, ImageMargins->0
, PlotRangeClipping->False
, AspectRatio->Full
, ImagePadding->None
, Background->[email protected]
]
; scrollbar = EventHandler[
scrollbar
, {
"MouseDown" :> (
mousePositionStart = MPY
; Which[ (*inside, maybe better vie MouseEntered?*)
mousePositionStart < scrollRawPosition
, scrollRawPosition = clipSRPos[scrollRawPosition - pageSize]
, mousePositionStart > scrollRawPosition + scrollHeight
, scrollRawPosition = clipSRPos[scrollRawPosition + pageSize]
, True, scrollRawPositionOffset = MPY - scrollRawPosition
]
)
, "MouseDragged" :> (
scrollRawPosition = clipSRPos[MPY - scrollRawPositionOffset]
)
}
]
(* visibility *)
; scrollbar = PaneSelector[
{ True -> scrollbar, False-> Spacer[0]}
, Dynamic[showScrollbar]
]
(* listener*)
; scrollbar = DynamicWrapper[scrollbar
, scrollPosition = 1 - Rescale[scrollRawPosition, {0 , 1-scrollHeight}, {0, 1}]
, TrackedSymbols :> {scrollRawPosition}
]
; scrollbar
]
]
];
ListPane // ClearAll;
ListPane // Options = {
ImageSize -> {All, 200},
"ItemWrapper" -> (Pane[##, ImageMargins->0]&)
};
ListPane[Dynamic[list_], OptionsPattern[]]:=With[
{
paneHeight = OptionValue[ImageSize][[2]],
itemHeight = 25,
totalLength = Length[list],
imageSize = OptionValue[ImageSize],
itemWrapper = OptionValue["ItemWrapper"]
}
, DynamicModule[
{
visibleLength = Ceiling[paneHeight/itemHeight],
visiblePart,
position = 1,
scrollPosition = 0
}
, visibleLength = Ceiling[paneHeight/itemHeight]
; visiblePart = Take[list,UpTo[visibleLength]]
; Module[
{pane}
, pane = Dynamic[ (*TODO: preburn*)
Column[
itemWrapper[#, ImageSize->{Full, itemHeight},ImageMargins->0, Alignment->{Left,Center}]&/@visiblePart
, Spacings->0
]
]
; Panel[
Grid[{{
pane
, DynamicWrapper[
VerticalScrollbar[Dynamic@scrollPosition, ImageSize -> {15, paneHeight}]
, position = Round @ Rescale[scrollPosition, {0,1}, {1, totalLength}]
; visiblePart = Take[list, {position, UpTo[position + visibleLength]}]
, TrackedSymbols:>{scrollPosition}
]
}}, Spacings->{1,0},Alignment->{Left,Top}]
, ImageSize->{imageSize[[1]], paneHeight+visibleLength-1}
, FrameMargins->0
, Alignment->{Right,Top}
, BaseStyle->CacheGraphics->False
]
]
]
];
And your updated code
Clear@SearchStrings
SearchStrings[input_: ""] :=
DynamicModule[{$input = input, matches = {}},
Panel[
Column@{Row[{
InputField[Dynamic[$input], String,
FieldHint -> "Enter company", FieldHintStyle -> {Gray},
BaseStyle -> {"ControlStyle"}, ContinuousAction -> True,
FieldSize -> 13],
Dynamic@
Text@Style[" (" <> ToString@Length[matches] <> " rows)", 11,
FontFamily -> "Verdana", FontWeight -> "Thin",
FontColor -> Gray]
}, " "
],
DynamicWrapper[
Dynamic[
ListPane[
Dynamic[matches], ImageSize -> {Full, 200},
"ItemWrapper" -> (Button[
Text@Style[#, 13, FontFamily -> "Verdana",
FontWeight -> "Thin", FontColor -> Black],
CopyToClipboard[#], Appearance -> "Frameless", ##2] &)
],
TrackedSymbols :> {matches}
],
matches = Cases[$sites, s_ /; StringContainsQ[s, $input], {-1}],
TrackedSymbols :> {$input}
]
}
,
ImageSize -> {300, All}]
]
$sites = ToString /@ Range[10000];
Deploy@SearchStrings[""]
FieldCompletionFunction
option forInputField
now. $\endgroup$Cases
is not slow. Typesetting and rendering of the long list of matched entries is. That is the problem in the 21117 question too. $\endgroup$