Move layout into settings
This removes the "Layout" button (which was confusingly short for
"toggle horizontal/vertical layout"), replacing it with a dropdown in
settings that can be Auto (default), Horizontal, or Vertical. The Auto
layout is horizontal for narrow windows and vertical for wide windows.
I also moved the Help button to the top right because I think it looks
better that way.
Test: tested manually
Change-Id: I75eac5545594f484371f228bc8431e5f64c3af9b
Reviewed-on: https://fuchsia-review.googlesource.com/c/fidlbolt/+/1066202
Reviewed-by: Ian McKellar <ianloic@google.com>
diff --git a/frontend/src/elm/Main.elm b/frontend/src/elm/Main.elm
index 6c515a2..a446b71 100644
--- a/frontend/src/elm/Main.elm
+++ b/frontend/src/elm/Main.elm
@@ -104,20 +104,32 @@
initCmd : Model -> Cmd Msg
initCmd model =
+ let
+ layout =
+ Settings.getLayout model.settings
+ in
Cmd.batch
[ Cmd.map DeploymentMsg Deployment.initCmd
, Cmd.map EditorMsg (Editors.initCmd model.editors)
, Cmd.map SettingsMsg (Settings.initCmd model.settings)
+ , Cmd.map SplitMsg (SplitPane.initCmd layout)
]
defaultModel : Settings.Scheme -> Model
defaultModel scheme =
+ let
+ settings =
+ Settings.init scheme
+
+ layout =
+ Settings.getLayout settings
+ in
{ deployment = Deployment.init
, share = Share.init
, editors = Editors.init
- , split = SplitPane.init SplitPane.Vertical 0.5 splitId
- , settings = Settings.init scheme
+ , split = SplitPane.init layout 0.5 splitId
+ , settings = settings
, news = News.init
, window = Window.init
}
@@ -178,11 +190,31 @@
( newSettings, settingsCmd ) =
Settings.update settingsMsg model.settings
+ layout =
+ Settings.getLayout newSettings
+
+ ( newSplit, splitCmd ) =
+ SplitPane.update (SplitPane.SetLayout layout) model.split
+
newModel =
- { model | settings = newSettings }
+ { model | settings = newSettings, split = newSplit }
+
+ cmds =
+ if settingsMsg == Settings.ClearDataAndReload then
+ -- We're about to reload, so avoid other commands which
+ -- could persist the model after we clear localStorage
+ -- but before the browser reloads the page.
+ [ settingsCmd ]
+
+ else
+ [ settingsCmd
+ , Cmd.map SplitMsg splitCmd
+ , Ports.resizeEditors
+ , persistModel newModel
+ ]
in
( newModel
- , Cmd.batch [ settingsCmd, persistModel newModel ]
+ , Cmd.batch cmds
)
ShareMsg shareMsg ->
@@ -208,7 +240,7 @@
cmds =
[ Cmd.map SplitMsg splitCmd
, case splitMsg of
- SplitPane.ToggleOrientation ->
+ SplitPane.AutoOrient _ ->
Cmd.batch
[ Ports.resizeEditors
, persistModel newModel
@@ -273,10 +305,14 @@
subscriptions : Model -> Sub Msg
subscriptions model =
+ let
+ layout =
+ Settings.getLayout model.settings
+ in
Sub.batch
[ Sub.map DeploymentMsg Deployment.subscriptions
, Sub.map ShareMsg Share.subscriptions
- , Sub.map SplitMsg (SplitPane.subscriptions model.split)
+ , Sub.map SplitMsg (SplitPane.subscriptions model.split layout)
, Sub.map WindowMsg (Window.subscriptions model.window)
]
@@ -378,9 +414,8 @@
Html.div
[ Attributes.class "controls-container" ]
[ button "Share" (toggle ShareWindow)
- , button "Help" (toggle HelpWindow)
, button "Settings" (toggle SettingsWindow)
- , button "Layout" (SplitMsg SplitPane.ToggleOrientation)
+ , button "Help" (toggle HelpWindow)
]
@@ -485,15 +520,6 @@
"""
]
, Html.li []
- [ text "Click the "
- , bold "Layout"
- , text " "
- , multiline """
-button to switch between the left/right editor layout and the top/bottom one
-(useful for long lines and narrow windows).
-"""
- ]
- , Html.li []
[ text "The app "
, bold "autosaves"
, text " "
diff --git a/frontend/src/elm/Settings.elm b/frontend/src/elm/Settings.elm
index 5aa75ea..1a0f624 100644
--- a/frontend/src/elm/Settings.elm
+++ b/frontend/src/elm/Settings.elm
@@ -5,12 +5,13 @@
module Settings exposing
( Model
- , Msg
+ , Msg(..)
, Scheme
, decode
, decodeScheme
, defaultScheme
, encode
+ , getLayout
, init
, initCmd
, themeClass
@@ -29,6 +30,7 @@
import Ports
import Regex
import Set exposing (Set)
+import SplitPane
@@ -75,6 +77,19 @@
"tomorrow_night"
+getLayout : Model -> SplitPane.Layout
+getLayout model =
+ case Form.getStringValue form "layout" model.form of
+ "horizontal" ->
+ SplitPane.Locked SplitPane.Horizontal
+
+ "vertical" ->
+ SplitPane.Locked SplitPane.Vertical
+
+ _ ->
+ SplitPane.Auto
+
+
getTheme : Model -> String
getTheme model =
Form.getStringValue form "theme" model.form
@@ -102,7 +117,8 @@
form : Form
form =
Form.define
- [ Form.groupedSelect "theme" "Theme" themes "textmate"
+ [ Form.select "layout" "Layout" layouts "auto"
+ , Form.groupedSelect "theme" "Theme" themes "textmate"
, Form.select "keyboardHandler" "Keybindings" keybindings "ace"
, Form.number "refreshDelay" "Refresh delay (ms)" 500 Form.positive
, Form.number "fontSize" "Font size" 14 Form.positive
@@ -135,6 +151,14 @@
]
+layouts : List ( Form.Identifier, String )
+layouts =
+ [ ( "auto", "Auto" )
+ , ( "horizontal", "Horizontal" )
+ , ( "vertical", "Vertical" )
+ ]
+
+
themes : List ( String, List ( Form.Identifier, String ) )
themes =
[ ( "Light"
diff --git a/frontend/src/elm/SplitPane.elm b/frontend/src/elm/SplitPane.elm
index ec73a2b..9c43996 100644
--- a/frontend/src/elm/SplitPane.elm
+++ b/frontend/src/elm/SplitPane.elm
@@ -4,12 +4,14 @@
module SplitPane exposing
- ( Model
+ ( Layout(..)
+ , Model
, Msg(..)
, Orientation(..)
, decode
, encode
, init
+ , initCmd
, subscriptions
, update
, view
@@ -59,6 +61,14 @@
}
+{-| Layout chosen by the user. Auto means Horizontal for narrow windows and
+Vertical for wide windows.
+-}
+type Layout
+ = Locked Orientation
+ | Auto
+
+
{-| Orientation can be confusing. This module uses the terms to refer to the
splitter, so Horizontal means top/bottom and Vertical means left/right.
-}
@@ -95,20 +105,36 @@
{-| Initializes a split pane. For example:
- init Vertical 0.5 "SplitContainer"
+ init Auto 0.5 "SplitContainer"
To use multiple split containers in a page, they must have unique IDs.
-}
-init : Orientation -> Position -> String -> Model
-init orientation splitPosition id =
- { orientation = orientation
+init : Layout -> Position -> String -> Model
+init layout splitPosition id =
+ { orientation =
+ case layout of
+ Locked orientation ->
+ orientation
+
+ Auto ->
+ Vertical
, state = Static splitPosition
, id = id
, bounds = emptyBounds
}
+initCmd : Layout -> Cmd Msg
+initCmd layout =
+ case layout of
+ Locked _ ->
+ Cmd.none
+
+ Auto ->
+ autoOrient
+
+
emptyBounds : Bounds
emptyBounds =
{ x = 0, y = 0, width = 0, height = 0 }
@@ -130,8 +156,10 @@
type Msg
= NoOp
- -- Toggles the orientation.
- | ToggleOrientation
+ -- Update the layout.
+ | SetLayout Layout
+ -- Set the orientation for the Auto layout, given the window width.
+ | AutoOrient Float
-- PreDragStart is necessary to kick off getting the container div bounds.
-- Without it, if you resize the window and then start dragging, there is
-- an annoying flicker effect.
@@ -163,17 +191,25 @@
NoOp ->
( model, Cmd.none )
- ToggleOrientation ->
- let
- orientation =
- case model.orientation of
- Horizontal ->
- Vertical
+ SetLayout layout ->
+ case layout of
+ Locked orientation ->
+ ( { model | orientation = orientation }, Cmd.none )
- Vertical ->
- Horizontal
- in
- ( { model | orientation = orientation }, Cmd.none )
+ Auto ->
+ ( model, autoOrient )
+
+ AutoOrient width ->
+ ( { model
+ | orientation =
+ if width < 1200 then
+ Horizontal
+
+ else
+ Vertical
+ }
+ , Cmd.none
+ )
PreDragStart ->
( model, startDrag model )
@@ -207,6 +243,11 @@
)
+autoOrient : Cmd Msg
+autoOrient =
+ Task.perform (\vp -> AutoOrient vp.viewport.width) Browser.Dom.getViewport
+
+
startDrag : Model -> Cmd Msg
startDrag model =
let
@@ -242,19 +283,33 @@
------------- SUBSCRIPTIONS ----------------------------------------------------
-subscriptions : Model -> Sub Msg
-subscriptions model =
- case model.state of
- Static _ ->
- Sub.none
+subscriptions : Model -> Layout -> Sub Msg
+subscriptions model layout =
+ let
+ mouseSubscriptions =
+ case model.state of
+ Static _ ->
+ []
- Moving _ ->
- Sub.batch
- [ Browser.Events.onMouseMove
- (Decode.map2 DragMove decodeMouseState decodeCoords)
- , Browser.Events.onMouseUp
- (Decode.map DragStop decodeCoords)
- ]
+ Moving _ ->
+ [ Browser.Events.onMouseMove
+ (Decode.map2 DragMove decodeMouseState decodeCoords)
+ , Browser.Events.onMouseUp
+ (Decode.map DragStop decodeCoords)
+ ]
+
+ handleResize =
+ \w _ -> AutoOrient (toFloat w)
+
+ resizeSubscriptions =
+ case layout of
+ Locked _ ->
+ []
+
+ Auto ->
+ [ Browser.Events.onResize handleResize ]
+ in
+ Sub.batch (mouseSubscriptions ++ resizeSubscriptions)
decodeMouseState : Decode.Decoder MouseState