How to convert between various ItemSize/ImageSize units?
You can access many different font characteristics via CurrentValue. Here is an approximation to convert between ItemSize and ImageSize:
itemSize = {10, 10};
Overlay[{
Grid[
{{"Sample", "Text"}}, Frame -> All, Spacings -> {0, 0},
ItemSize -> itemSize, Alignment -> {Left, Center}],
Row[{
Framed["Sample", ImageSize ->
Dynamic[itemSize*{CurrentValue["FontMWidth"],
CurrentValue["FontLineHeight"]}],
FrameMargins -> 0, FrameStyle -> Blue],
Framed["Text", ImageSize ->
Dynamic[itemSize*{CurrentValue["FontMWidth"],
CurrentValue["FontLineHeight"]}],
FrameMargins -> 0, FrameStyle -> Blue]}]
}]
This seems to work on my system at least, but as Mr.Wizard said it might be system dependent
lineHeight = 1.5;
conversion = 10;(*magic number*)
scrollToThis = 80;
paneHeight = 200;
pos = (scrollToThis - 1/2)*lineHeight*conversion - paneHeight/2;
Framed[
Pane[
Grid[List /@ data, Frame -> All,
ItemSize -> {5, lineHeight},
Background -> {White, {scrollToThis -> Red}}, Spacings -> {0, 0}],
ImageSize -> {100, paneHeight}, Scrollbars -> {False, True},
ScrollPosition -> {0, pos}, ImageMargins -> 0, FrameMargins -> 0],
ImageMargins -> 0, FrameMargins -> 0]
With these settings the highlighted cell always appears in the middle of the Pane
independent of the values of scrollToThis
, paneHeight
, and lineHeight
(provided lineHeight>1
).
Alternatively, you could wrap each cell in the Grid in a Pane with a fixed height and use that to scroll to the right position:
scrollToThis = 80;
cellHeight = 20;
margins = 1;
width = 120;
paneHeight = 200;
gr = Grid[List[Pane[#, {width - 20, cellHeight},
Alignment -> {Center, Center}, ImageMargins -> margins]] & /@
data,
Frame -> All, ItemSize -> {Automatic, Automatic},
Spacings -> {0, 0}, Alignment -> {Center, Center},
Background -> {White, {scrollToThis -> Red}}];
pos = (scrollToThis - 1/2)*(cellHeight + 2 margins) - paneHeight/2;
Framed[
Pane[gr, ImageSize -> {width, paneHeight},
Scrollbars -> {False, True}, ScrollPosition -> {0, pos},
ImageMargins -> 0, FrameMargins -> 0],
ImageMargins -> 0, FrameMargins -> 0]
It's not really the done thing to answer a question you've set a bounty on, but here is an explanation of why Mike's answer isn't quite right. The first point to note is that item sizes include the width of frames, so one needs to allow for the thickness of the frames in the ImageSize
option for the second grid (thus the +2
in the option since FrameStyle
has a setting including AbsoluteThickness[1]
and you need to count both sides.)
It's also necessary to ensure ContentPadding
is False
. This affects placement of the text in the grid cell.
Finally, Row
doesn't take the Spacings
option while Grid
does. In these circumstances it helps to used Grid
for both cases. Notice I've used the Offset
specification of spacing, which only counts the spacing excluding frames and borders.
Overlay[{Grid[{{"Sample", "Text"}}, Frame -> All,
FrameStyle -> Directive[AbsoluteThickness[1], Red],
Spacings -> {Offset[0], 0}, ItemSize -> itemSize,
Alignment -> {Left, Center}],
Grid[{{Framed["Sample",
ImageSize -> 2 + Dynamic[
itemSize*{CurrentValue["FontMWidth"],
CurrentValue["FontLineHeight"]}], FrameMargins -> 0,
BaseStyle -> Red,
FrameStyle -> Directive[AbsoluteThickness[1], Blue],
ContentPadding -> False],
Framed["Text",
ImageSize ->
Dynamic[{2, 2} +
itemSize*{CurrentValue["FontMWidth"],
CurrentValue["FontLineHeight"]}], FrameMargins -> 0,
BaseStyle -> Red,
FrameStyle -> Directive[AbsoluteThickness[1], Blue],
ContentPadding -> False]}}, Spacings -> {Offset[0], 0}]}]