50 lines
3.6 KiB
Plaintext
50 lines
3.6 KiB
Plaintext
DataGrid[
|
|
rowHeights:{__Integer},
|
|
colWidths:{__Integer},
|
|
spacings:{_Integer,_Integer},
|
|
borderWidths:{{_Integer,_Integer},{_Integer,_Integer}},
|
|
options_Association,
|
|
data:{__List?MatrixQ}]:=
|
|
With[
|
|
(*Need to make sure we have sensible defaults for the decoration options.*)
|
|
{alignment=Lookup[options,"alignment",{0,0}],
|
|
background=Lookup[options,"background"," "],
|
|
dividers=Lookup[options,"dividers",{" "," "," "}],
|
|
border=Lookup[options,"border"," "],
|
|
dims={Length[rowHeights],Length[colWidths]}},
|
|
(*Pad the data so that it will fit into the specified rectangle (list of lists).*)
|
|
With[{augmentedData=PadRight[data,Times@@dims,{{{background}}}]},
|
|
(*Create a matrix of dimensions based on desired rectangle. Once we have a matrix of cells we can "thread" these two matrices and use that data to coerce each cell into its final dimensions.*)
|
|
With[{cellDims=ArrayReshape[Outer[List,rowHeights,colWidths],{Times@@dims,2}]},
|
|
(*MatrixAlign, defined below, rescales and aligns each cell's data.*)
|
|
With[{undecoratedGrid=Partition[MapThread[MatrixAlign[alignment,#1,background][#2]&, {cellDims,augmentedData}],dims[[2]]]},
|
|
(*Add the spacing to each row.*)
|
|
With[{dividedRows=MapThread[Transpose[Riffle[#2,{ConstantArray[dividers[[2]],{#1,spacings[[2]]}]},{2,-2,2}]]&, {rowHeights,undecoratedGrid}]},
|
|
(*Add the spacing between rows.*)
|
|
With[{dividedColumn=Riffle[dividedRows,{Transpose[Riffle[ConstantArray[dividers[[1]],{spacings[[1]],#}]&/@colWidths,{ConstantArray[dividers[[3]],spacings]},{2,-2,2}]]},{2,-2,2}]},
|
|
(*Assemble all cell rows into actual character rows. We now have one large matrix.*)
|
|
With[{dividedGrid=Catenate[Map[Flatten,dividedColumn,{2}]]},
|
|
(*Add borders.*)
|
|
ArrayPad[dividedGrid,borderWidths,border]]]]]]]];
|
|
|
|
DataGrid[dims:{_Integer,_Integer},spacings_,borderWidths_,options_,data:{__List?MatrixQ}]:=
|
|
(*Calculate the max height for each row and max width for each column, and then just call the previous DataGrid function above.*)
|
|
With[
|
|
{rowHeights=Flatten@BlockMap[Max[Part[#,All,All,1]]&,ArrayReshape[Dimensions/@data,Append[dims,2],1],{1,dims[[2]]}],
|
|
colWidths=Flatten@BlockMap[Max[Part[#,All,All,2]]&,ArrayReshape[Dimensions/@data,Append[dims,2],1],{dims[[1]],1}]},
|
|
DataGrid[rowHeights,colWidths,spacings,borderWidths,options,data]];
|
|
|
|
(*This could probably be simplified, but I like having all of the aligment options explicit and separate for testability.*)
|
|
MatrixAlign[{-1,-1},dims_,pad_]:=PadRight[#,dims,pad]&;
|
|
MatrixAlign[{-1,0},dims_,pad_]:=PadRight[CenterArray[#,{Dimensions[#][[1]],dims[[2]]},pad],dims,pad]&;
|
|
MatrixAlign[{-1,1},dims_,pad_]:=PadRight[PadLeft[#,{Dimensions[#][[1]],dims[[2]]},pad],dims,pad]&;
|
|
MatrixAlign[{0,-1},dims_,pad_]:=CenterArray[PadRight[#,{Dimensions[#][[1]],dims[[2]]},pad],dims,pad]&;
|
|
MatrixAlign[{0,0},dims_,pad_]:=CenterArray[#,dims,pad]&;
|
|
MatrixAlign[{0,1},dims_,pad_]:=CenterArray[PadLeft[#,{Dimensions[#][[1]],dims[[2]]},pad],dims,pad]&;
|
|
MatrixAlign[{1,-1},dims_,pad_]:=PadLeft[PadRight[#,{Dimensions[#][[1]],dims[[2]]},pad],dims,pad]&;
|
|
MatrixAlign[{1,0},dims_,pad_]:=PadLeft[CenterArray[#,{Dimensions[#][[1]],dims[[2]]},pad],dims,pad]&;
|
|
MatrixAlign[{1,1},dims_,pad_]:=PadLeft[#,dims,pad]&;
|
|
|
|
(*While the grid functions make no assumptions about the format of the data, we will be using them with string/character data, and we will eventually want to output a calendar as a single large string. AsString gives us a standard method for transforming a matrix of characters into a string with rows delimited by newlines.*)
|
|
AsString[matrix_List?MatrixQ]:=StringRiffle[matrix,"\n",""];
|