/elm-ui-window

Primary LanguageElmBSD 3-Clause "New" or "Revised" LicenseBSD-3-Clause

elm-ui-window

Put some draggable, resizeable rectangles to your UI!

Use cases

Usage

You basically have this type...

type alias Window msg =
{ rect : Rect
, render : (Msg -> msg) -> Int -> Rect -> Element msg
, resize : Resize
}

...that you can use with three familiar functions: initWith, update and view.

That's it!

Example

A fully working example would be:

type alias Model =
    { windowModel : Window.Model
    }


init : Model
init =
    { windowModel = Window.initWith windows
    }


type Msg
    = WindowMsg Window.Msg


update : Msg -> Model -> ( Model, Cmd msg )
update msg model =
    case msg of
        WindowMsg windowMsg ->
            let
                ( windowModel, windowCmds ) =
                    Window.update windowMsg model.windowModel
            in
            ( { windowModel = windowModel }, windowCmds )


view : Model -> Html Msg
view model =
    layout []
        -- Mount the view wherever you want
        (Window.view WindowMsg model.windowModel windows)


windows : List (Window.Window msg)
windows =
    -- A window is just a rect in xy space and some render fn to render the content inside that rect. That's it!
    [ -- A rect is a rectangle with a position and size
      { rect =
            { position = vec2 0 0
            , size = vec2 100 100
            }

      -- A simple view render function. You don't have to use the `_ _ _` params, hence the `_`.
      , render =
            \_ _ _ ->
                -- Just give it some style and you are good to go!
                el [ Element.Border.width 3 ] (text "Hello, World!")

      -- Handles how resize should be handled
      , resize = HideAnchorPoints
      }
    ]

Advanced usage

In the simple example we ignored three params of the render function. These three params actually are: toMsg, index, and rect. Let's see how we can use them to create advanced views:

windows2 : List (Window.Window msg)
windows2 =
    [ { rect =
            { position = vec2 0 0
            , size = vec2 100 100
            }
      , render =
            \toMsg ix rect ->
                column
                    [ Element.Border.width 3

                    -- Use the toMsg to use the `onDrag` function to allow for you window to be dragged.
                    -- This can be whereever you like, either everywhere oder at dedicated area like a window title bar.
                    , onDrag toMsg ix
                    ]
                    -- Use the index and current rect state if you want to use them
                    [ text <| "index  = " ++ String.fromInt ix
                    , text <| "x      = " ++ String.fromFloat (getX rect.position)
                    , text <| "y      = " ++ String.fromFloat (getY rect.position)
                    , text <| "width  = " ++ String.fromFloat (getX rect.size)
                    , text <| "height = " ++ String.fromFloat (getY rect.size)
                    ]
      , resize = ShowAnchorPoints
      }
    ]

Notes

You can find the example in src/Window/Example.elm.

This is work in progress and therfore not yet published on elm packages.