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.

I've run into a Grid layout problem for which I don't know a solution. I want to specify alignment to a specific character such as a decimal and an ItemSize on a per-Item basis. When I try to do this the decimal ends up on the right edge of the field rather than somewhere in the middle. My application is part of a larger, more complex Grid layout but here is a simple illustration:

gridIt[itemopts__] :=
 Module[{x},
  x = {{1.234, 12.34}, {123.4, 1234.}, {1234, 1.234}};
  x = Map[Item[#, itemopts] &, x, {2}];
  x = Prepend[x, {"Title", SpanFromLeft}];
  Grid[x, Alignment -> {Center, Center}, Dividers -> All]
 ]

gridIt[Alignment -> "."]

Mathematica graphics

gridIt[Alignment -> ".", ItemSize -> 4.4]

Mathematica graphics

Why does this happen and how can I work around it?

share|improve this question
1  
One possible workaround is to use the Alignment -> \[AlignmentMarker] option and embed the \[AlignmentMarker] in the numbers as I showed here. –  Alexey Popkov Oct 21 '12 at 6:09
    
@Alexey would you please consider posting that as an answer, and including an example? –  Mr.Wizard Oct 21 '12 at 7:18
    
How about -- and this is ugly -- if you converted to strings and padded a fixed distance from the decimal point with whitespace? ...assuming you don't want to just pad right with zeros. –  Mike Honeychurch Oct 22 '12 at 0:06
add comment

4 Answers

Give items more space on the right, set Spacings explicitly:

gridIt[itemopts__] := 
 Module[{x}, x = {{1.234, 12.34}, {123.4, 1234.}, {1234, 1.234}};
  x = Map[Item[#, itemopts] &, x, {2}];
  x = Prepend[x, {"Title", SpanFromLeft}];
  Grid[x, Alignment -> {Center, Center}, Dividers -> All, 
   Spacings -> {{2 -> 6, 3 -> 6}, Automatic}]]

gridIt[Alignment -> ".", ItemSize -> 4.4]

enter image description here

share|improve this answer
    
Interesting, but that has way too much white-space. What can be done? –  Mr.Wizard Oct 20 '12 at 10:15
    
Yeah, I was also unsatisfied with it. That spacing spec puts white space on both sides of a divider. Not sure if we can do it on 1 side. Maybe compensate somehow with ItemSize - differently for left and right columns? –  Vitaliy Kaurov Oct 20 '12 at 10:23
add comment

It is definitely a bug in Grid. Here is a workaround:

format[x_?NumericQ, spaces : {left_: 5, right_: 5}] := 
 MapAt[Row[{Spacer[left], #, Spacer[right]}] &, 
  SciForm[x, 4, -2, Align -> "."], 1]

Module[{x}, x = {{1.234, 12.34}, {123.4, 1234.}, {1234, 1.234}};
 x = Map[format[#, {7, 7}] &, x, {2}];
 x = Prepend[x, {Item["Title", Alignment -> Center], SpanFromLeft}];
 Grid[x, Alignment -> {Automatic, Center}, Dividers -> All]]

table

The SciForm function is from this post.

share|improve this answer
    
I momentarily upvoted this, but when I try to use ItemSize it still breaks. Could you please show how I am supposed to control absolute cell width? –  Mr.Wizard Oct 21 '12 at 8:13
    
@Mr.Wizard In the format function you should change the values 5 in Spacer[5]. It is the way to control absolute cell width. –  Alexey Popkov Oct 21 '12 at 14:38
    
@Mr.Wizard I updated the format function. –  Alexey Popkov Oct 21 '12 at 14:51
1  
Alexey, the problem then is that it is relative width, or more specifically width + X spacing (margin). Suppose elements in the left and right columns are not the same lengths, but I want the columns to have the same absolute width. In this case I cannot use a fixed spacing, I need an ItemSize. Do you see what I am fighting with? Please know that I do appreciate your effort on this. –  Mr.Wizard Oct 21 '12 at 14:58
1  
@Mr.Wizard Unfortunately, at the moment I do not see any way to create a "normal" ItemSize or fix the bug. Only this not too easy-to-use workaround. But I am very interested in a solution or proper fix too. I think WRI must fix this really annoying problem. –  Alexey Popkov Oct 21 '12 at 15:38
show 2 more comments

This is messy:

If made the numbers strings and padded with whitespace:

padded[x_, cutoff_: 6] := Module[{tmp1, tmp2},
  tmp1 = StringSplit[ToString[x], "."];
  If[Length[tmp1] == 2,
   tmp2 = StringTake[tmp1[[2]] <> "      ", cutoff];
   tmp1[[1]] <> "." <> tmp2,
   tmp1[[1]] <> StringTake["       ", cutoff + 1]
   ]
  ]

I've made the cut off 6 because the default print precision is 6 so default you'll have at most 6 characters after the decimal place.

So now the revised gridIt:

ClearAll[gridIt];

gridIt[cutoff_, itemopts : OptionsPattern[{Grid}]] := Module[{x},
  x = Map[padded[#, cutoff] &, {{1.234, 12.34}, {123.4, 
      1234.}, {1234, 1.234}}, {2}];
  x = Map[Item[#, itemopts] &, x, {2}];
  x = Prepend[x, {"Title", SpanFromLeft}];
  Grid[x, Alignment -> {Center, Center}, Dividers -> All]]

gridIt[6, Alignment -> {Right, Center}]

gridIt[2, Alignment -> {Right, Center}, ItemSize -> 5]

enter image description here

As you shrink the item size you need to reduce the cut off value.

This is all a bit clumsy but may do the job.

share|improve this answer
add comment

Does this work as a workaround?

gridIt[itemopts__] := 
 Module[{x}, x = {{1.234, 12.34}, {123.4, 1234.}, {1234, 1.234}};
  x = Map[Item[#, itemopts] &, x, {2}];
  Column[{"Title",
    Grid[x, Alignment -> {Center, Center}, Dividers -> All]
    }, Dividers -> {True, {True}}, Spacings -> {-0.1, {0.5, 0.2}}, 
   Alignment -> Center]]
share|improve this answer
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.