git.iko.soy/typeable/elm-ui
on master help sign in
270 lines 7.8 kB history raw
1module Internal.Grid exposing (Around, Layout(..), PositionedElement, RelativePosition(..), build, createGrid, getWidth, relative)
3{-| Relative positioning within a grid.
5A relatively positioned grid, means a 3x3 grid with the primary element in the center.
7-}
9import Element
10import Internal.Flag as Flag
11import Internal.Model as Internal
14type RelativePosition
15 = OnRight
16 | OnLeft
17 | Above
18 | Below
19 | InFront
22type Layout
23 = GridElement
24 | Row
25 | Column
28type alias Around alignment msg =
29 { right : Maybe (PositionedElement alignment msg)
30 , left : Maybe (PositionedElement alignment msg)
31 , primary : ( Maybe String, List (Internal.Attribute alignment msg), List (Internal.Element msg) )
33 -- , primaryWidth : Internal.Length
34 , defaultWidth : Internal.Length
35 , below : Maybe (PositionedElement alignment msg)
36 , above : Maybe (PositionedElement alignment msg)
37 , inFront : Maybe (PositionedElement alignment msg)
38 }
41type alias PositionedElement alignment msg =
42 { layout : Layout
43 , child : List (Internal.Element msg)
44 , attrs : List (Internal.Attribute alignment msg)
45 , width : Int
46 , height : Int
47 }
50relative : Maybe String -> List (Internal.Attribute alignment msg) -> Around alignment msg -> Internal.Element msg
51relative node attributes around =
52 let
53 ( sX, sY ) =
54 Internal.getSpacing attributes ( 7, 7 )
56 make positioned =
57 Internal.element Internal.noStyleSheet
58 Internal.asEl
59 Nothing
60 positioned.attrs
61 (Internal.Unkeyed positioned.child)
63 ( template, children ) =
64 createGrid ( sX, sY ) around
65 in
66 Internal.element Internal.noStyleSheet
67 Internal.asGrid
68 node
69 (template ++ attributes)
70 (Internal.Unkeyed
71 children
72 )
75createGrid : ( Int, Int ) -> Around alignment msg -> ( List (Internal.Attribute alignment msg1), List (Element.Element msg) )
76createGrid ( spacingX, spacingY ) nearby =
77 let
78 rowCount =
79 List.sum
80 [ 1
81 , if Nothing == nearby.above then
82 0
84 else
85 1
86 , if Nothing == nearby.below then
87 0
89 else
90 1
91 ]
93 colCount =
94 List.sum
95 [ 1
96 , if Nothing == nearby.left then
97 0
99 else
100 1
101 , if Nothing == nearby.right then
102 0
104 else
105 1
106 ]
108 rows =
109 if nearby.above == Nothing then
110 { above = 0
111 , primary = 1
112 , below = 2
113 }
115 else
116 { above = 1
117 , primary = 2
118 , below = 3
119 }
121 columns =
122 if Nothing == nearby.left then
123 { left = 0
124 , primary = 1
125 , right = 2
126 }
128 else
129 { left = 1
130 , primary = 2
131 , right = 3
132 }
134 rowCoord pos =
135 case pos of
136 Above ->
137 rows.above
139 Below ->
140 rows.below
142 OnRight ->
143 rows.primary
145 OnLeft ->
146 rows.primary
148 InFront ->
149 rows.primary
151 colCoord pos =
152 case pos of
153 Above ->
154 columns.primary
156 Below ->
157 columns.primary
159 OnRight ->
160 columns.right
162 OnLeft ->
163 columns.left
165 InFront ->
166 columns.primary
168 place pos el =
169 build (rowCoord pos) (colCoord pos) spacingX spacingY el
170 in
171 ( [ Internal.StyleClass Flag.gridTemplate
172 (Internal.GridTemplateStyle
173 { spacing = ( Internal.Px spacingX, Internal.Px spacingY )
174 , columns =
175 List.filterMap identity
176 [ nearby.left
177 |> Maybe.map (\el -> Maybe.withDefault nearby.defaultWidth (getWidth el.attrs))
178 , nearby.primary
179 |> (\( node, attrs, el ) -> getWidth attrs)
180 |> Maybe.withDefault nearby.defaultWidth
181 |> Just
182 , nearby.right
183 |> Maybe.map (\el -> Maybe.withDefault nearby.defaultWidth (getWidth el.attrs))
184 ]
185 , rows = List.map (always Internal.Content) (List.range 1 rowCount)
186 }
187 )
188 ]
189 , List.filterMap identity
190 [ Just <|
191 case nearby.primary of
192 ( primaryNode, primaryAttrs, primaryChildren ) ->
193 Internal.element Internal.noStyleSheet
194 Internal.asEl
195 primaryNode
196 (Internal.StyleClass Flag.gridPosition
197 (Internal.GridPosition
198 { row = rows.primary
199 , col = columns.primary
200 , width = 1
201 , height = 1
202 }
203 )
204 :: primaryAttrs
205 )
206 (Internal.Unkeyed primaryChildren)
207 , Maybe.map (place OnLeft) nearby.left
208 , Maybe.map (place OnRight) nearby.right
209 , Maybe.map (place Above) nearby.above
210 , Maybe.map (place Below) nearby.below
211 , Maybe.map (place InFront) nearby.inFront
212 ]
213 )
216build : Int -> Int -> Int -> Int -> { a | attrs : List (Internal.Attribute alignment msg), height : Int, layout : Layout, width : Int, child : List (Internal.Element msg) } -> Internal.Element msg
217build rowCoord colCoord spacingX spacingY positioned =
218 let
219 attributes =
220 Internal.StyleClass Flag.gridPosition
221 (Internal.GridPosition
222 { row = rowCoord
223 , col = colCoord
224 , width = positioned.width
225 , height = positioned.height
226 }
227 )
228 :: Internal.StyleClass Flag.spacing (Internal.SpacingStyle spacingX spacingY)
229 :: positioned.attrs
230 in
231 case positioned.layout of
232 GridElement ->
233 Internal.element Internal.noStyleSheet
234 Internal.asEl
235 Nothing
236 attributes
237 (Internal.Unkeyed <| positioned.child)
239 Row ->
240 Internal.element Internal.noStyleSheet
241 Internal.asRow
242 Nothing
243 attributes
244 (Internal.Unkeyed positioned.child)
246 Column ->
247 Internal.element Internal.noStyleSheet
248 Internal.asColumn
249 Nothing
250 attributes
251 (Internal.Unkeyed positioned.child)
254getWidth : List (Internal.Attribute align msg) -> Maybe Internal.Length
255getWidth attrs =
256 let
257 widthPlease attr found =
258 case found of
259 Just x ->
260 Just x
262 Nothing ->
263 case attr of
264 Internal.Width w ->
265 Just w
267 _ ->
268 Nothing
269 in
270 List.foldr widthPlease Nothing attrs