timjs / elm-collage

Create interactive vector graphics and position them relative to each other
BSD 3-Clause "New" or "Revised" License
58 stars 19 forks source link

Make LineStyle and FillStyle separate arguments to styled and remove Style alias #9

Open timjs opened 6 years ago

timjs commented 6 years ago

This is a reminiscence from the Elm Render library's ShapeStyle. Note that styled in Elm Collage is more similar to styledShape than to filledAndBordered. I tried to simplify things and merge these to ways to add fill and outline to a shape. It is a hard one to design properly. ShapeStyle was a record, I made Style a tuple. Take a look at these two simple fills and outlines:

rectangle 100 50
    |> filled (uniform blue)

rectangle 100 50
    |> outlined (solid thick (uniform red))

and the three possible options to use styled with undefined styles:

-- Option 1: separate arguments
rectangle 100 50
    |> styled (uniform blue) (solid thick (uniform red))

-- Option 2: tuple
rectangle 100 50
    |> styled ( uniform blue, solid thick (uniform red) )

-- Option 3: record
rectangle 100 50
    |> styled { fill = uniform blue, line = solid thick (uniform red) }

As for parentheses, it doesn't matter that much. You'll need them anyway in option 1 and option 2. I think option 3 is way to verbose and contains unnecessary information.

Now comes the deliberation: How does it look like when using predefined styles?

--
-- Option 1: separate arguments => create styling functions
--
outlinedAndFilled thickness fillColor =
    styled (uniform fillColor) (solid thickness (uniform black))

thinOutlinedAndFilled =
    outlinedAndFilled thin

thickOutlinedAndFilled =
    outlinedAndFilled thick

triangle 30
    |> thickOutlinedAndFilled green

--
-- Option 2: tuple => create new `Style` tuple
--
thinOutlinedAndFilled fillColor =
    ( uniform fillColor, solid thin (uniform black) )

thickOutlinedAndFilled fillColor =
    let
        (fill, line) =
            thinOutlinedAndFilled fillColor
    in
    ( fill, {line | thickness = thick} )

triangle 30
    |> styled (thickOutlinedAndFilled green)

--
-- Option 3: record => create new `Style` record
--
thinOutlinedAndFilled fillColor =
    { fill = uniform fillColor, line = solid thin (uniform black) }

thickOutlinedAndFilled fillColor =
    let
        old =
            thinOutlinedAndFilled fillColor

        -- Elm doesn't accept an expression before the bar in records...
        old_line =
            old.line
    in
    { old | line = {old_line | thickness = thick} }

triangle 30
    |> styled (thickOutlinedAndFilled green)

I'm not sure any more if using a type alias for a shape style consisting of a tuple or a record is a good idea. Probably good old currying and abstraction are indeed our biggest friends here!

This was brought up in #4.