16
$\begingroup$

How can one convert between the implicit units used by Grid (ems and line height for horizontal and vertical dimensions) and printers points (in GraphicsGrid and Graphics)?

Grid[{{"sample", "text"}}, Frame -> All, 
 ItemSize -> {{4, 7}, Automatic}]

Row@{Framed["sample", ImageSize -> 60, FrameMargins -> 0], 
  Framed["sample", ImageSize -> 100, FrameMargins -> 0]}

GraphicsGrid[{{"sample", "text"}}, Frame -> All, ItemSize -> 7]

GraphicsGrid[{{Item["sample", ItemSize -> 4], 
   Item["text", ItemSize -> 7]}}, Frame -> All(*,ImageSize->160*)]

Mathematica graphics

The last two examples show that, while the documentation of ItemSize states that "In GraphicsGrid, w and h are both measured in absolute printer's points", ItemSize cannot be used as an option for GraphicsGrid and it doesn't do anything as an option for an internal object wrapped in Item.

Realistic example

Here is a particular problem, that presents the issue of different units in the same object. The task is to automatically scroll a Pane to a certain line in a dataset. Updated: Improved code according to Heike, to keep the line in focus at the top.

data = Range@200;
lineHeight = 1.5;
conversion = 14; (* magic number *)
paneHeight = 120;

update[n_] := (scrollToThis = n; 
   pos = (scrollToThis - 1)*lineHeight*conversion);
update@1;

Row@{Slider[Dynamic[scrollToThis, (update@#) &], {1, Length@data, 1}],
   "  line: ", Dynamic@scrollToThis, "   at position: ", Dynamic@pos}
Dynamic[Framed[
  Pane[Grid[List /@ data, Frame -> All, ItemSize -> {5, lineHeight}, 
    Background -> {White, {scrollToThis -> Red}}],
   ImageSize -> {100, paneHeight}, Scrollbars -> {False, True}, 
   ScrollPosition -> {0, pos}, ImageMargins -> 0, FrameMargins -> 0], 
  ImageMargins -> 0, FrameMargins -> 0], 
 TrackedSymbols :> {scrollToThis, pos}]

Mathematica graphics

Question

Is there a way to convert between different units (ems / lineheight <--> printers points) in a foolproof way?

$\endgroup$
8
  • $\begingroup$ For reference I need a "magic number" of 22.77 on my machine. $\endgroup$
    – Mr.Wizard
    Feb 10, 2012 at 10:43
  • $\begingroup$ Regarding your example, if ScrollPosition only accepts pixel measurements as briefly skimming the help suggests I don't see how this can be done reliably. $\endgroup$
    – Mr.Wizard
    Feb 10, 2012 at 10:46
  • $\begingroup$ @Mr.Wizard: I would assume that lineheight depends on actual screen size/resolution/other factors, which are accessible in Mathematica, though I don't want to go through discovering the relationship if anyone else has already done this. $\endgroup$ Feb 10, 2012 at 10:50
  • $\begingroup$ I think it's just too complicated. I expect that it varies with version and platform. $\endgroup$
    – Mr.Wizard
    Feb 10, 2012 at 10:52
  • 3
    $\begingroup$ wikipedia says 1 em is always whatever the point setting is. In Mma I'd interpret that as meaning if the base style is 12 then 1 em is 12. If the base style is 18 then 1 em is 18 -- assuming it has been implemented that way in Mma. en.wikipedia.org/wiki/Em_%28typography%29 $\endgroup$ Feb 10, 2012 at 21:51

3 Answers 3

6
$\begingroup$

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}]}]

enter image description here

$\endgroup$
2
  • $\begingroup$ I would gladly give the bounty to you, if it would be possible. $\endgroup$ Jun 23, 2012 at 0:43
  • $\begingroup$ alas, that's not allowed, since it was mine :) $\endgroup$
    – Verbeia
    Jun 23, 2012 at 1:18
8
+50
$\begingroup$

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]}]
}]

enter image description here

$\endgroup$
3
  • $\begingroup$ The output looks totally different on my computer (Win7-64, MMA 8.04). The test words don't overlap at all and the boxes are shifted. However, this is only so the first time I execute this code, but if I run it a second time it looks like your picture. Strange. $\endgroup$ Jun 17, 2012 at 11:13
  • $\begingroup$ Same thing on Mac 10.8, MMA 8.04, but things don't line back up when I run it a second time. $\endgroup$ Jun 21, 2012 at 14:11
  • $\begingroup$ @Mike you had quite a bit of the answer but it needs some fixing up, for example using some of the material in my answer. If you can do this in the next 12 hours I can award the bounty. Otherwise it will expire. $\endgroup$
    – Verbeia
    Jun 22, 2012 at 5:14
7
$\begingroup$

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]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.