1 /// 2 module fluid.structs; 3 4 import std.conv; 5 6 7 @safe: 8 9 10 enum NodeAlign { 11 12 start, center, end, fill 13 14 } 15 16 /// Create a new layout 17 /// Params: 18 /// expand = Numerator of the fraction of space this node should occupy in the parent. 19 /// align_ = Align of the node (horizontal and vertical). 20 /// alignX = Horizontal align of the node. 21 /// alignY = Vertical align of the node. 22 Layout layout(uint expand, NodeAlign alignX, NodeAlign alignY) pure { 23 24 return Layout(expand, [alignX, alignY]); 25 26 } 27 28 /// Ditto 29 Layout layout(uint expand, NodeAlign align_) pure { 30 31 return Layout(expand, align_); 32 33 } 34 35 /// Ditto 36 Layout layout(NodeAlign alignX, NodeAlign alignY) pure { 37 38 return Layout(0, [alignX, alignY]); 39 40 } 41 42 /// Ditto 43 Layout layout(NodeAlign align_) pure { 44 45 return Layout(0, align_); 46 47 } 48 49 /// Ditto 50 Layout layout(uint expand) pure { 51 52 return Layout(expand); 53 54 } 55 56 /// CTFE version of the layout constructor, allows using strings instead of enum members, to avoid boilerplate. 57 Layout layout(uint expand, string alignX, string alignY)() pure { 58 59 enum valueX = alignX.to!NodeAlign; 60 enum valueY = alignY.to!NodeAlign; 61 62 return Layout(expand, [valueX, valueY]); 63 64 } 65 66 /// Ditto 67 Layout layout(uint expand, string align_)() pure { 68 69 enum valueXY = align_.to!NodeAlign; 70 71 return Layout(expand, valueXY); 72 73 } 74 75 /// Ditto 76 Layout layout(string alignX, string alignY)() pure { 77 78 enum valueX = alignX.to!NodeAlign; 79 enum valueY = alignY.to!NodeAlign; 80 81 return Layout(0, [valueX, valueY]); 82 83 } 84 85 /// Ditto 86 Layout layout(string align_)() pure { 87 88 enum valueXY = align_.to!NodeAlign; 89 90 return Layout(0, valueXY); 91 92 } 93 94 /// Ditto 95 Layout layout(uint expand)() pure { 96 97 return Layout(expand); 98 99 } 100 101 unittest { 102 103 assert(layout!1 == layout(1)); 104 assert(layout!("fill") == layout(NodeAlign.fill, NodeAlign.fill)); 105 assert(layout!("fill", "fill") == layout(NodeAlign.fill)); 106 107 assert(!__traits(compiles, layout!"expand")); 108 assert(!__traits(compiles, layout!("expand", "noexpand"))); 109 assert(!__traits(compiles, layout!(1, "whatever"))); 110 assert(!__traits(compiles, layout!(2, "foo", "bar"))); 111 112 } 113 114 /// Represents a node's layout 115 struct Layout { 116 117 /// Fraction of available space this node should occupy in the node direction. 118 /// 119 /// If set to `0`, the node doesn't have a strict size limit and has size based on content. 120 uint expand; 121 122 /// Align the content box to a side of the occupied space. 123 NodeAlign[2] nodeAlign; 124 125 string toString() const { 126 127 import std.format; 128 129 const equalAlign = nodeAlign[0] == nodeAlign[1]; 130 const startAlign = equalAlign && nodeAlign[0] == NodeAlign.start; 131 132 if (expand) { 133 134 if (startAlign) return format!".layout!%s"(expand); 135 else if (equalAlign) return format!".layout!(%s, %s)"(expand, nodeAlign[0]); 136 else return format!".layout!(%s, %s, %s)"(expand, nodeAlign[0], nodeAlign[1]); 137 138 } 139 140 else { 141 142 if (startAlign) return format!"Layout()"; 143 else if (equalAlign) return format!".layout!%s"(nodeAlign[0]); 144 else return format!".layout!(%s, %s)"(nodeAlign[0], nodeAlign[1]); 145 146 } 147 148 } 149 150 } 151 152 /// Node core constructor parameters, to be passed from node to node. 153 struct NodeParams { 154 155 import fluid.style; 156 157 Layout layout; 158 Theme theme; 159 160 this(Layout layout, Theme theme = null) { 161 162 this.layout = layout; 163 this.theme = theme; 164 165 } 166 167 /// Ditto 168 this(Theme theme, Layout layout = Layout.init) { 169 170 this(layout, theme); 171 172 } 173 174 }