src/Gui/Gui.elm (228 lines of code) (raw):

module Gui.Gui exposing ( Msg, Model , view, update, build , moves, ups, downs , extractMouse ) import Gui.Def exposing (..) import Gui.Msg exposing (..) import Gui.Nest exposing (..) import Gui.Grid exposing (..) import Gui.Mouse exposing (..) import Gui.Util exposing (..) type alias Model umsg = ( MouseState, Nest umsg ) type alias View umsg = Grid umsg type alias Msg umsg = Gui.Msg.Msg umsg view = Tuple.second >> Gui.Grid.view --moves mstate = Gui.Mouse.moves mstate >> TrackMouse moves gui pos = extractMouse gui |> Gui.Mouse.moves pos |> TrackMouse --ups mstate = Gui.Mouse.ups mstate >> TrackMouse ups gui pos = extractMouse gui |> Gui.Mouse.ups pos |> TrackMouse --downs mstate = Gui.Mouse.downs mstate >> TrackMouse downs gui pos = extractMouse gui |> Gui.Mouse.downs pos |> TrackMouse extractMouse : Model umsg -> MouseState extractMouse = Tuple.first build : Nest umsg -> Model umsg build nest = ( Gui.Mouse.init, nest ) update : (umsg -> umodel -> ( umodel, Cmd umsg )) -> umodel -> Msg umsg -> Model umsg -> ( ( umodel, Cmd umsg ), Model umsg ) update userUpdate userModel msg ( ( mouse, ui ) as model ) = case msg of TrackMouse newMouse -> update userUpdate userModel (findMessageForMouse model newMouse) ( newMouse, ui ) FocusOn pos -> ( ( userModel, Cmd.none ) , ui |> shiftFocusTo pos |> withMouse mouse ) Tune pos alter -> ( ( userModel, Cmd.none ) , ui |> shiftFocusTo pos |> updateCell pos (\cell -> case cell of Knob label setup curValue handler -> Knob label setup (alterKnob setup alter curValue) handler _ -> cell ) |> withMouse mouse ) ToggleOn pos -> ( ( userModel, Cmd.none ) , ui |> shiftFocusTo pos |> updateCell pos (\cell -> case cell of Toggle label _ handler -> Toggle label TurnedOn handler _ -> cell ) |> withMouse mouse ) ToggleOff pos -> ( ( userModel, Cmd.none ) , ui |> shiftFocusTo pos |> updateCell pos (\cell -> case cell of Toggle label _ handler -> Toggle label TurnedOff handler _ -> cell ) |> withMouse mouse ) ExpandNested pos -> ( ( userModel, Cmd.none ) , ui |> shiftFocusTo pos |> collapseAllAbove pos |> updateCell pos (\cell -> case cell of Nested label _ cells -> Nested label Expanded cells _ -> cell ) |> withMouse mouse ) CollapseNested pos -> ( ( userModel, Cmd.none ) , ui |> shiftFocusTo pos |> updateCell pos (\cell -> case cell of Nested label _ cells -> Nested label Collapsed cells _ -> cell ) |> withMouse mouse ) ExpandChoice pos -> ( ( userModel, Cmd.none ) , ui |> collapseAllAbove pos |> shiftFocusTo pos |> updateCell pos (\cell -> case cell of Choice label _ selection handler cells -> Choice label Expanded selection handler cells _ -> cell ) |> withMouse mouse ) CollapseChoice pos -> ( ( userModel, Cmd.none ) , ui |> shiftFocusTo pos |> updateCell pos (\cell -> case cell of Choice label _ selection handler cells -> Choice label Collapsed selection handler cells _ -> cell ) |> withMouse mouse ) Select pos -> ( ( userModel, Cmd.none ) , let parentPos = getParentPos pos |> Maybe.withDefault nowhere index = getIndexOf pos |> Maybe.withDefault -1 in ui |> shiftFocusTo pos |> updateCell parentPos (\cell -> case cell of Choice label expanded selection handler cells -> Choice label expanded index handler cells _ -> cell ) |> withMouse mouse ) SendToUser userMsg -> ( userUpdate userMsg userModel , ui |> withMouse mouse ) SelectAndSendToUser pos userMsg -> sequenceUpdate userUpdate userModel [ Select pos, SendToUser userMsg ] ( ui |> withMouse mouse ) ToggleOnAndSendToUser pos userMsg -> sequenceUpdate userUpdate userModel [ ToggleOn pos, SendToUser userMsg ] ( ui |> withMouse mouse ) ToggleOffAndSendToUser pos userMsg -> sequenceUpdate userUpdate userModel [ ToggleOff pos, SendToUser userMsg ] ( ui |> withMouse mouse ) ShiftFocusLeftAt pos -> ( ( userModel, Cmd.none ) , ui |> shiftFocusBy -1 pos |> withMouse mouse ) ShiftFocusRightAt pos -> ( ( userModel, Cmd.none ) , ui |> shiftFocusBy 1 pos |> withMouse mouse ) TuneAndApply pos alter userMsg -> sequenceUpdate userUpdate userModel [ Tune pos alter, SendToUser userMsg ] ( ui |> withMouse mouse ) NoOp -> ( ( userModel, Cmd.none ) , ui |> withMouse mouse ) withMouse : MouseState -> Nest umsg -> Model umsg withMouse = Tuple.pair -- findMessageForMouse : MouseState -> MouseState -> Focus -> Cell umsg -> Msg umsg -- findMessageForMouse prevMouseState nextMouseState focusedPos focusedCell = findMessageForMouse : Model umsg -> MouseState -> Msg umsg findMessageForMouse ( prevMouseState, ui ) nextMouseState = let (Focus focusedPos) = findFocus ui in case findCell focusedPos ui of Just (Knob _ knobState curValue handler) -> let alter = applyMove prevMouseState nextMouseState knobState curValue in if (prevMouseState.down == True && nextMouseState.down == False) then TuneAndApply focusedPos alter <| handler (alterKnob knobState alter curValue) else Tune focusedPos alter _ -> NoOp sequenceUpdate : (umsg -> umodel -> ( umodel, Cmd umsg )) -> umodel -> List (Msg umsg) -> Model umsg -> ( ( umodel, Cmd umsg ), Model umsg ) sequenceUpdate userUpdate userModel msgs ui = List.foldr (\msg ( ( prevUserModel, prevCommand ), prevUi ) -> let ( ( newUserModel, newUserCommand ), newUi ) = update userUpdate prevUserModel msg prevUi in ( ( newUserModel , Cmd.batch [ prevCommand, newUserCommand ] ) , newUi ) ) ( ( userModel, Cmd.none ), ui ) msgs