Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question
    
For reference I need a "magic number" of 22.77 on my machine. –  Mr.Wizard Feb 10 '12 at 10:43
    
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. –  Mr.Wizard Feb 10 '12 at 10:46
    
@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. –  István Zachar Feb 10 '12 at 10:50
    
I think it's just too complicated. I expect that it varies with version and platform. –  Mr.Wizard Feb 10 '12 at 10:52
2  
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 –  Mike Honeychurch Feb 10 '12 at 21:51
show 3 more comments

3 Answers 3

up vote 8 down vote accepted

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]
share|improve this answer
add comment

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

share|improve this answer
    
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. –  Sjoerd C. de Vries Jun 17 '12 at 11:13
    
Same thing on Mac 10.8, MMA 8.04, but things don't line back up when I run it a second time. –  R Hall Jun 21 '12 at 14:11
    
@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. –  Verbeia Jun 22 '12 at 5:14
add comment

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

share|improve this answer
    
I would gladly give the bounty to you, if it would be possible. –  István Zachar Jun 23 '12 at 0:43
    
alas, that's not allowed, since it was mine :) –  Verbeia Jun 23 '12 at 1:18
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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