14

Bug introduced in 7.0 or earlier and persisting through 11.0 or later. Fixed in 13.0.0 or earlier


I have run into another problem with Grid today.
An explicitly specified ItemSize is being ignored:

dot = Graphics[{Pink, Disk[]}, ImageSize -> 40];

tab = {{"Type", "Name", [SpanFromLeft], [SpanFromLeft], Item[dot, ItemSize -> 2.7], Item["Esculap", Alignment -> Left], [SpanFromLeft], [SpanFromLeft]}, {[SpanFromAbove], "Dia.", "Spec", [SpanFromLeft], [SpanFromAbove], Item[8.3 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right], Item[11, Alignment -> Right], "6.3"}, {Item[dot, ItemSize -> 2.7], Item["Flycatcher", Alignment -> Left], [SpanFromLeft], [SpanFromLeft], Item[dot, ItemSize -> 2.7], Item["Apus", Alignment -> Left], [SpanFromLeft], [SpanFromLeft]}, {[SpanFromAbove], Item[6.9 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right], Item[17, Alignment -> Right], "9.8", [SpanFromAbove], Item[7.8 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right], Item[8, Alignment -> Right], "6.7"}};

Grid[tab, Spacings -> {Automatic, {{0, -1.1}}}, Alignment -> {Center, Center}, Dividers -> All ]

Mathematica graphics

Please note Item[8.3 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right] where a vertical ItemSize is explicitly specified, yet it is ignored in the layout.

If the "Spec" cell is not spanned this does not happen:

tab[[2, 4]] = "X";

Grid[tab, Spacings -> {Automatic, {{0, -1.1}}}, Alignment -> {Center, Center}, Dividers -> All ]

Mathematica graphics

  • Is this another bug in Grid?

  • Is it still present in version 8?

  • How can I best work around it?

bmf
  • 15,157
  • 2
  • 26
  • 63
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • 2
    I can confirm that the output of your code looks just the same in MMA ver. 8.0.4. – m_goldberg Oct 21 '12 at 15:14
  • 2
    @m_goldberg Thanks. I have only recently tried to set up a nice looking Grid with spanned cells and I must say I'm finding it an aggravating experience. – Mr.Wizard Oct 21 '12 at 15:24
  • Is the title misleading? Can you be sure ItemSize is causing the problem? Would something like "Grid -- nested spanning causing problem" be better? – m_goldberg Oct 21 '12 at 15:58
  • My point is that ItemSize is being ignored. If you leave out ItemSize then the bottom (twin) row looks like the top one. I was trying to keep the title distinct from this one. – Mr.Wizard Oct 21 '12 at 16:04
  • Can it be due to your Spacings setting? I find that Spacings -> {Automatic, {{0}, -1.3}} gets me a much better layout. You have to cut away a bit of vertical spacing in the last row only, not in all other rows. – Sjoerd C. de Vries Oct 21 '12 at 19:37
  • @Sjoerd Spacings certainly is part of the picture, but my settings are intentional (at least the way I believe them to work) to get a layout that is not too unlike the target here. Yours do not do that. – Mr.Wizard Oct 21 '12 at 20:23
  • Which of those outputs is your target? – Sjoerd C. de Vries Oct 21 '12 at 20:29
  • @Sjoerd the TableForm ones, and also this one here; I want the two lines of text closely spaced with a nice margin above and below. – Mr.Wizard Oct 21 '12 at 20:31
  • 1
    It works fine on my Mathematica 11.3 (Mathematica running in local, Windows 7). In the cloud (Mma version 12) the problem you mention is not present, but there are other problems of the same kind (ItemSize vertical specification ignored). – andre314 Jul 26 '19 at 21:07

3 Answers3

8

The usual quick-and-dirty workaround when ItemSize does not do what is expected is to wrap contents into an invisible frame. One can use Framed with FrameStyle->None to hide the frame or Pane. In both cases, a magic number is required to convert between line-height of Grid and printers points of Framed/Pane - it is highly platform-specific (see here). The simplified example with Pane:

dot = Graphics[{Pink, Disk[]}, ImageSize -> 40];

magic = 10;

tab = {
   {"Type", "Name", \[SpanFromLeft], \[SpanFromLeft], dot, 
    "Esculap", \[SpanFromLeft], \[SpanFromLeft]},
   {\[SpanFromAbove], "Dia.", 
    "Spec", \[SpanFromLeft], \[SpanFromAbove], 8.3 "mm", 
    Pane[11, {Automatic, 2.7*magic}, Alignment -> Center], "6.3"},
   {dot, "Flycatcher", \[SpanFromLeft], \[SpanFromLeft], dot, 
    "Apus", \[SpanFromLeft], \[SpanFromLeft]},
   {\[SpanFromAbove], 6.9 "mm", 17, "9.8", \[SpanFromAbove], 7.8 "mm",
     Item[8, ItemSize -> {Automatic, 2.7}], "6.7"}
   };

Grid[tab, Spacings -> {Automatic, {{0, -1.1}}}, 
 Alignment -> {Center, Center}, Dividers -> All]

Mathematica graphics

One can get rid of the overhang (gap with missing dividers) by wrapping Item around the cell:

Item[Pane[11, {Automatic, 2.7*magic}, Alignment -> Center]]

Mathematica graphics

This issue of gaps is only present in version 8. My guess is that as ContentPadding -> True was added to Pane in version 8 only, in version 7 a different behaviour is the default for padding inside Pane that does not introduce these gaps. However, calling the above example with ContentPadding -> False in v8 does not remove the gaps contradily to my expectations.

An almost identical result can be obtained if given cell is wrapped in Framed (note the horizontal increase in size of the cell):

Framed[11, ImageSize -> {Automatic, 2.7*magic}, FrameStyle -> None]

Mathematica graphics

István Zachar
  • 47,032
  • 20
  • 143
  • 291
  • This works somewhat better than the workaround I came up with using Spacer. +1 – Mr.Wizard Oct 22 '12 at 08:44
  • If going this route it may be somewhat cleaner to use Pane[11, {All, 2.7 magic}, Alignment -> Center] – Mr.Wizard Oct 22 '12 at 08:49
  • True that, I forgot about Pane. Actually one (being fool enough) could try to reimplement Grid by using only Pane, Framed and similar constructs. This would be a hell of a task getting all the boxes to align to each other... – István Zachar Oct 22 '12 at 08:51
  • My fallback if I cannot wrestle Grid into submission is to construct a Graphics object with Text, Inset, etc. I'm hoping to avoid that. – Mr.Wizard Oct 22 '12 at 08:53
  • BTW if you look very closely at the example you'll see that the white frame overlaps the divider. It would be better to use FrameStyle -> None I believe. – Mr.Wizard Oct 22 '12 at 08:56
  • Yes, I was aware of it hence the "ugly" qualifier in the text. Should I include your Pane solution as well, or you want to post it as your own answer? – István Zachar Oct 22 '12 at 08:57
  • Please feel free to rewrite this answer using Pane; I think it's the logical step. (I don't see the need to keep Framed too, other than perhaps a comment in passing.) – Mr.Wizard Oct 22 '12 at 08:59
  • Done. This post now makes more sense, hopefully would help lots who wrestle hopelessly with the layout engine of Grid. – István Zachar Oct 22 '12 at 09:10
  • What input produces the one with big gaps? Do you need both Pane and Item in version 8? It looks fine with only Pane for me (v7). – Mr.Wizard Oct 22 '12 at 09:32
  • Yes, Pane introduces gaps, and adding an extra Item[...] solves this issue. Added some explanation and a guess. – István Zachar Oct 22 '12 at 09:56
  • I tried the above code with ver. 8.0.4 on OS X without the Item or Frame work-arounds, and I don't see any gaps. Maybe problem is platform specific? Or maybe it only exists in ver. 8.0.x, where x < 4? – m_goldberg Oct 22 '12 at 17:53
  • @m_goldberg: I use 8.0.4 as well under Win7. – István Zachar Oct 22 '12 at 19:52
  • @IstvánZachar. Looks like a Win 7 problem then, doesn't it? – m_goldberg Oct 23 '12 at 00:11
  • @m_goldberg Could be, but I cannot test that at the moment. Will try to close in on this tomorrow with another machine. – István Zachar Oct 23 '12 at 09:23
4

I don't have a real answer, but here are two work-arounds. I don't have any real expectation that you will like either ;-)

Work-around 1

The idea here is that since there are actually two Spec values, the lengend should also have two fileds, each telling the viewer what one of each of the parameters represents.

dot = Graphics[{Pink, Disk[]}, ImageSize -> 40];

tab = {{"Type", "Name", \[SpanFromLeft], \[SpanFromLeft], 
        Item[dot, ItemSize -> 2.7], Item["Esculap", Alignment -> Left],
        \[SpanFromLeft], \[SpanFromLeft]},
       {\[SpanFromAbove], "Dia.", "Spec 1", "Spec 2", \[SpanFromAbove], 
        Item[8.3 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right], 
        Item[11, Alignment -> Right], "6.3"},
       {Item[dot, ItemSize -> 2.7], Item["Flycatcher", Alignment -> Left],
        \[SpanFromLeft], \[SpanFromLeft], Item[dot, ItemSize -> 2.7], 
        Item["Apus", Alignment -> Left], \[SpanFromLeft], \[SpanFromLeft]},
       {\[SpanFromAbove], Item[6.9 "mm", ItemSize -> {3.5, 2.7},
                                         Alignment -> Right], 
        Item[17, Alignment -> Right], "9.8", \[SpanFromAbove], 
        Item[7.8 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right], 
        Item[8, Alignment -> Right], "6.7"}};

Grid[tab, Spacings -> {Automatic, {{0, -1.1}}}, 
          Alignment -> {Center, Center}, Dividers -> All]

This outputs

enter image description here

Work-around 2

The idea here is that, given there is only one legend slot, all the other sub-tables should have only one corresponding slot. The two values shown in the combined slots should be shown separated by a suitable delimiter.

makeStr = (StringJoin @@ ToString /@ {##}) &;

dot = Graphics[{Pink, Disk[]}, ImageSize -> 40];

tab = {{"Type", "Name", \[SpanFromLeft], Item[dot, ItemSize -> 2.7], 
        Item["Esculap", Alignment -> Left], \[SpanFromLeft]},
      {\[SpanFromAbove], "Dia.", "Spec", \[SpanFromAbove], 
       Item[8.3 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right], 
       makeStr[11, ", ", 6.3]},
      {Item[dot, ItemSize -> 2.7], Item["Flycatcher", Alignment -> Left],
       \[SpanFromLeft], Item[dot, ItemSize -> 2.7], 
       Item["Apus", Alignment -> Left], \[SpanFromLeft]},
      {\[SpanFromAbove], Item[6.9 "mm", ItemSize -> {3.5, 2.7},
                                        Alignment -> Right], 
       makeStr[7, ", ", 9.8], \[SpanFromAbove], 
       Item[7.8 "mm", ItemSize -> {3.5, 2.7}, Alignment -> Right], 
       makeStr[8, ", ", 6.7]}};

Grid[tab, Spacings -> {Automatic, {{0, -1.1}}}, 
          Alignment -> {Center, Center}, Dividers -> All]

This outputs

enter image description here

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
  • These are, unsurprisingly, the two options I am aware of. I'm holding my vote for now as I am hoping for some other answer, but it's good that you've documented them. Incidentally you could use makeStr = Row@{##} &;. – Mr.Wizard Oct 21 '12 at 20:26
  • No, I'm not surprised you were aware of these work-arounds, but I felt they should be explicitly put on the table. You did ask for work-arounds. – m_goldberg Oct 21 '12 at 22:19
  • Did you actually try your version of makeStr? It was the first thing I thought of, but it didn't work for me. – m_goldberg Oct 21 '12 at 22:22
  • Indeed I did, and it appears to work in version 7 for this example. How does it fail for you? – Mr.Wizard Oct 21 '12 at 22:26
  • I have figured out what I did wrong. My version, because of bad typing was makeStr = (Row@{#})&. – m_goldberg Oct 21 '12 at 23:01
3

The situation appears to have been fixed in V13.0.0 or earlier. Grabbing the code from the OP and executing it, gives:

bugfixed

bmf
  • 15,157
  • 2
  • 26
  • 63