{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DefaultSignatures #-}

{- | SwiftUI-like view tree

The layout keeps the propose-report-place protocol, but chops some parts away.

* Views are abstracted and the 'View' constructor punches a hole in a tree (a hollow?) for a UI toolkit to fill in later.
* There's no "tree builder", so containers and modifiers are constructed directly. Although it is easy to recover modifier with the "Data.Function.(&)" operator.
* There's no "ideal size", "fixed size" etc. and the views are fully flexible. The UI tookit wrappers can instead self-wrap their Views in a 'Frame'/'FlexibleFrame' as needed.
-}

module Geomancy.Layout.View where

import Data.Bifunctor (Bifunctor(..))
import Data.Foldable (toList)
import Data.Foldable1 (foldMap1')
import Data.Functor.Identity (Identity)
import Data.List (mapAccumL, foldl', sortOn)
import Data.List.NonEmpty (nonEmpty)
import Geomancy ((^*))
import Geomancy.Gl.Funs (glClamp)
import Geomancy.Layout qualified as Layout
import Geomancy.Layout.Alignment (Alignment)
import Geomancy.Layout.Alignment qualified as Alignment
import Geomancy.Layout.Box (Box(..))
import Geomancy.Layout.Box qualified as Box
import Geomancy.Vec2 (Vec2, vec2, withVec2, pattern WithVec2)
import Geomancy.Vec4 (Vec4, withVec4)
import GHC.Arr (array)

-- | Run all the layout steps to annotate the nodes with their final placement boxes.
layout :: LayoutView stuff => Box -> View () stuff -> View Box (Placed stuff)
layout :: forall stuff.
LayoutView stuff =>
Box -> View () stuff -> View Box (Placed stuff)
layout Box
initialBox = Box -> View ViewSize stuff -> View Box (Placed stuff)
forall stuff.
LayoutView stuff =>
Box -> View ViewSize stuff -> View Box (Placed stuff)
place Box
initialBox (View ViewSize stuff -> View Box (Placed stuff))
-> (View () stuff -> View ViewSize stuff)
-> View () stuff
-> View Box (Placed stuff)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure

-- | Do all of the layout steps and fold placed views
--
-- Mostly an example. The better way is to cache intermediate steps.
--
-- (Actually a pun on "fold views".)
foldWith :: (LayoutView stuff, Monoid a) => (Placed stuff -> a) -> Box -> View () stuff -> a
foldWith :: forall stuff a.
(LayoutView stuff, Monoid a) =>
(Placed stuff -> a) -> Box -> View () stuff -> a
foldWith Placed stuff -> a
f Box
initialBox = (Placed stuff -> a) -> View Box (Placed stuff) -> a
forall m a. Monoid m => (a -> m) -> View Box a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Placed stuff -> a
f (View Box (Placed stuff) -> a)
-> (View () stuff -> View Box (Placed stuff)) -> View () stuff -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Box -> View ViewSize stuff -> View Box (Placed stuff)
forall stuff.
LayoutView stuff =>
Box -> View ViewSize stuff -> View Box (Placed stuff)
place Box
initialBox (View ViewSize stuff -> View Box (Placed stuff))
-> (View () stuff -> View ViewSize stuff)
-> View () stuff
-> View Box (Placed stuff)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure

{- | An interface to plug UI toolkits into the layout.

Alternatively, convert them to `ViewFun`, which has the instance.

The "minimal: none" is a lie. Most likely you will need to adjust either 'ReportedCache ' or 'Placed' types and implement the other function accordingly.

The most gnarly code would be for "rendered text" widgets since they would be dynamically sized and have to be processed/cached on each step.
-}
class LayoutView stuff where
  -- | Measurement pre-pass
  viewFlexibility :: stuff -> ViewSize

  -- XXX: argument order is optimized for \case

  -- | Propose step: return the actual size and store intermediate data.
  proposeView :: Vec2 -> stuff -> (Vec2, ReportedCache stuff)
  type ReportedCache stuff
  type ReportedCache stuff = stuff

  -- | Placement step: get the reported size augmented with a final position, produce the result.
  placeView :: Box -> ReportedCache stuff -> Placed stuff
  type Placed stuff
  type Placed stuff = stuff

  -- | Default implementation is "the view *will* adapt to any size"
  default viewFlexibility :: stuff -> ViewSize
  viewFlexibility = ViewSize -> stuff -> ViewSize
forall a b. a -> b -> a
const ViewSize
infinite_

  -- | Default implementation for "accept everything" reporting
  default proposeView :: (ReportedCache stuff ~ stuff) => Vec2 -> stuff -> (Vec2, ReportedCache stuff)
  proposeView = (,)

  -- | Default implementation for "box function" placement
  default placeView :: (ReportedCache stuff ~ (Box -> Placed stuff)) => Box -> ReportedCache stuff -> Placed stuff
  placeView Box
placed ReportedCache stuff
f = ReportedCache stuff
Box -> Placed stuff
f Box
placed

-- | "Variant-lite" instance to mix widgets of different type
--
-- XXX: the foldable/traversable would skip the Lefts.
-- Use something like `foldWith` to pre-process and normalize to a common "backend" type
instance (LayoutView l, LayoutView r) => LayoutView (Either l r) where
  type ReportedCache (Either l r) = Either (ReportedCache l) (ReportedCache r)
  type Placed (Either l r) = Either (Placed l) (Placed r)
  viewFlexibility :: Either l r -> ViewSize
viewFlexibility = (l -> ViewSize) -> (r -> ViewSize) -> Either l r -> ViewSize
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either l -> ViewSize
forall stuff. LayoutView stuff => stuff -> ViewSize
viewFlexibility r -> ViewSize
forall stuff. LayoutView stuff => stuff -> ViewSize
viewFlexibility
  proposeView :: Vec2 -> Either l r -> (Vec2, ReportedCache (Either l r))
proposeView Vec2
proposed = (l -> (Vec2, Either (ReportedCache l) (ReportedCache r)))
-> (r -> (Vec2, Either (ReportedCache l) (ReportedCache r)))
-> Either l r
-> (Vec2, Either (ReportedCache l) (ReportedCache r))
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((ReportedCache l -> Either (ReportedCache l) (ReportedCache r))
-> (Vec2, ReportedCache l)
-> (Vec2, Either (ReportedCache l) (ReportedCache r))
forall a b. (a -> b) -> (Vec2, a) -> (Vec2, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ReportedCache l -> Either (ReportedCache l) (ReportedCache r)
forall a b. a -> Either a b
Left ((Vec2, ReportedCache l)
 -> (Vec2, Either (ReportedCache l) (ReportedCache r)))
-> (l -> (Vec2, ReportedCache l))
-> l
-> (Vec2, Either (ReportedCache l) (ReportedCache r))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vec2 -> l -> (Vec2, ReportedCache l)
forall stuff.
LayoutView stuff =>
Vec2 -> stuff -> (Vec2, ReportedCache stuff)
proposeView Vec2
proposed) ((ReportedCache r -> Either (ReportedCache l) (ReportedCache r))
-> (Vec2, ReportedCache r)
-> (Vec2, Either (ReportedCache l) (ReportedCache r))
forall a b. (a -> b) -> (Vec2, a) -> (Vec2, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ReportedCache r -> Either (ReportedCache l) (ReportedCache r)
forall a b. b -> Either a b
Right ((Vec2, ReportedCache r)
 -> (Vec2, Either (ReportedCache l) (ReportedCache r)))
-> (r -> (Vec2, ReportedCache r))
-> r
-> (Vec2, Either (ReportedCache l) (ReportedCache r))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vec2 -> r -> (Vec2, ReportedCache r)
forall stuff.
LayoutView stuff =>
Vec2 -> stuff -> (Vec2, ReportedCache stuff)
proposeView Vec2
proposed)
  placeView :: Box -> ReportedCache (Either l r) -> Placed (Either l r)
placeView Box
placed = \case
    Left ReportedCache l
x -> Placed l -> Either (Placed l) (Placed r)
forall a b. a -> Either a b
Left (Placed l -> Either (Placed l) (Placed r))
-> Placed l -> Either (Placed l) (Placed r)
forall a b. (a -> b) -> a -> b
$ forall stuff.
LayoutView stuff =>
Box -> ReportedCache stuff -> Placed stuff
placeView @l Box
placed ReportedCache l
x
    Right ReportedCache r
x -> Placed r -> Either (Placed l) (Placed r)
forall a b. b -> Either a b
Right (Placed r -> Either (Placed l) (Placed r))
-> Placed r -> Either (Placed l) (Placed r)
forall a b. (a -> b) -> a -> b
$ forall stuff.
LayoutView stuff =>
Box -> ReportedCache stuff -> Placed stuff
placeView @r Box
placed ReportedCache r
x

{- | Do-nothing pass-through instance

You'll have to peek at the @View{ann}@ of the placement tree.
-}
instance LayoutView (Identity stuff) where
  viewFlexibility :: Identity stuff -> ViewSize
viewFlexibility = ViewSize -> Identity stuff -> ViewSize
forall a b. a -> b -> a
const ViewSize
infinite_
  proposeView :: Vec2 -> Identity stuff -> (Vec2, ReportedCache (Identity stuff))
proposeView = (,)
  placeView :: Box -> ReportedCache (Identity stuff) -> Placed (Identity stuff)
placeView Box
_placed = Identity stuff -> Identity stuff
ReportedCache (Identity stuff) -> Placed (Identity stuff)
forall a. a -> a
id

{- | A model type for the protocol

The fields correspond to the 3 steps:

* Measurement into ViewSize - static.
* Proposing and reporting - depends on parent size / caches size-related data.
* Placement - depends on placement ('Box' = reported size + position), can use cached data.
-}
data ViewFun stuff = ViewFun ViewSize (Vec2 -> (Vec2, Box -> stuff))
  deriving ((forall a b. (a -> b) -> ViewFun a -> ViewFun b)
-> (forall a b. a -> ViewFun b -> ViewFun a) -> Functor ViewFun
forall a b. a -> ViewFun b -> ViewFun a
forall a b. (a -> b) -> ViewFun a -> ViewFun b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> ViewFun a -> ViewFun b
fmap :: forall a b. (a -> b) -> ViewFun a -> ViewFun b
$c<$ :: forall a b. a -> ViewFun b -> ViewFun a
<$ :: forall a b. a -> ViewFun b -> ViewFun a
Functor)

-- | A wrapper to construct 'ViewFun'-based views
viewFun :: ViewSize -> (Vec2 -> (Vec2, Box -> stuff)) -> View () (ViewFun stuff)
viewFun :: forall stuff.
ViewSize
-> (Vec2 -> (Vec2, Box -> stuff)) -> View () (ViewFun stuff)
viewFun ViewSize
flex Vec2 -> (Vec2, Box -> stuff)
steps = View{ann :: ()
ann=(), stuff :: ViewFun stuff
stuff=ViewSize -> (Vec2 -> (Vec2, Box -> stuff)) -> ViewFun stuff
forall stuff.
ViewSize -> (Vec2 -> (Vec2, Box -> stuff)) -> ViewFun stuff
ViewFun ViewSize
flex Vec2 -> (Vec2, Box -> stuff)
steps}

-- | A wrapper to construct 'ViewFun'-based views by assuming infinite flex and no intrinsic size
boxFun :: (Box -> stuff) -> View () (ViewFun stuff)
boxFun :: forall stuff. (Box -> stuff) -> View () (ViewFun stuff)
boxFun Box -> stuff
f = ViewSize
-> (Vec2 -> (Vec2, Box -> stuff)) -> View () (ViewFun stuff)
forall stuff.
ViewSize
-> (Vec2 -> (Vec2, Box -> stuff)) -> View () (ViewFun stuff)
viewFun ViewSize
infinite_ (,Box -> stuff
f)

instance LayoutView (ViewFun stuff) where
  type ReportedCache (ViewFun stuff) = Box -> stuff -- ^ Propose to resolve the outer
  type Placed (ViewFun stuff) = stuff
  viewFlexibility :: ViewFun stuff -> ViewSize
viewFlexibility (ViewFun ViewSize
vs Vec2 -> (Vec2, Box -> stuff)
_) = ViewSize
vs
  proposeView :: Vec2 -> ViewFun stuff -> (Vec2, ReportedCache (ViewFun stuff))
proposeView Vec2
size (ViewFun ViewSize
_ Vec2 -> (Vec2, Box -> stuff)
f) = Vec2 -> (Vec2, Box -> stuff)
f Vec2
size
  placeView :: Box -> ReportedCache (ViewFun stuff) -> Placed (ViewFun stuff)
placeView Box
placed ReportedCache (ViewFun stuff)
f = ReportedCache (ViewFun stuff)
Box -> stuff
f Box
placed

-- * View tree

{- | Layout skeleton

It is Functor-Foldable-Traversable on 'View' so you can use things like 'Control.Monad.void' to suppress payload and 'show' the intermediate structure.
-}
data View ann stuff
  = View
      { forall ann stuff. View ann stuff -> ann
ann :: ann
      , forall ann stuff. View ann stuff -> stuff
stuff :: stuff
      } -- ^ UI-specific payload
  | Spacer
      { ann :: ann
      }

  -- "containers"
  | HStack
      { ann :: ann
        -- TODO: placement direction
        -- TODO: spacing to inject
      , forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View ann stuff]
      } -- ^ Place children side-by-side (LTR)
  | VStack
      { ann :: ann
        -- TODO: placement direction
        -- TODO: spacing to inject
      , children :: [View ann stuff]
      } -- ^ Place children top-to-bottom
  | ZStack
      { ann :: ann
      , children :: [View ann stuff]
      } -- ^ Place children atop of each other
  | Overlay
      { ann :: ann
      , forall ann stuff. View ann stuff -> View ann stuff
secondary :: View ann stuff
      , forall ann stuff. View ann stuff -> View ann stuff
primary :: View ann stuff
      } -- ^ Propose the size of the primary view to the secondary view

  -- "modifiers"
  | Frame
      { ann :: ann
      , forall ann stuff. View ann stuff -> Vec2
size :: Vec2
      , forall ann stuff. View ann stuff -> Alignment
align :: Alignment
      , forall ann stuff. View ann stuff -> View ann stuff
inner :: View ann stuff
      } -- ^ Propose/report size unconditionally
  | FlexibleFrame
      { ann :: ann
      , forall ann stuff. View ann stuff -> ViewSize
flex :: ViewSize -- ^ Acceptable size ranges
      , align :: Alignment
      , inner :: View ann stuff
      } -- ^ Adjust measurement flex and clamp proposed/reported size
  | AspectRatio
      { ann :: ann
      , forall ann stuff. View ann stuff -> Vec2
aspect :: Vec2 -- ^ Like 'Ratio Float', for example @vec2 16 9@ or @1@ (= @vec2 1 1@, i.e. square)
      , align :: Alignment
      -- TODO: fit/crop
      , inner :: View ann stuff
      } -- ^ Frame-like wrapper that fits
  | Padding
      { ann :: ann
      , forall ann stuff. View ann stuff -> TRBL
trbl :: Box.TRBL
      , inner :: View ann stuff
      } -- ^ Subtracts a CSS-tyle padding (top/right/bottom/left) from parent
  | Offset
      { ann :: ann
      , forall ann stuff. View ann stuff -> Vec2
xy :: Vec2
      , inner :: View ann stuff
      } -- ^ Adds offset when placing a view
  deriving (View ann stuff -> View ann stuff -> Bool
(View ann stuff -> View ann stuff -> Bool)
-> (View ann stuff -> View ann stuff -> Bool)
-> Eq (View ann stuff)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall ann stuff.
(Eq stuff, Eq ann) =>
View ann stuff -> View ann stuff -> Bool
$c== :: forall ann stuff.
(Eq stuff, Eq ann) =>
View ann stuff -> View ann stuff -> Bool
== :: View ann stuff -> View ann stuff -> Bool
$c/= :: forall ann stuff.
(Eq stuff, Eq ann) =>
View ann stuff -> View ann stuff -> Bool
/= :: View ann stuff -> View ann stuff -> Bool
Eq, Int -> View ann stuff -> ShowS
[View ann stuff] -> ShowS
View ann stuff -> String
(Int -> View ann stuff -> ShowS)
-> (View ann stuff -> String)
-> ([View ann stuff] -> ShowS)
-> Show (View ann stuff)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall ann stuff.
(Show stuff, Show ann) =>
Int -> View ann stuff -> ShowS
forall ann stuff.
(Show stuff, Show ann) =>
[View ann stuff] -> ShowS
forall ann stuff.
(Show stuff, Show ann) =>
View ann stuff -> String
$cshowsPrec :: forall ann stuff.
(Show stuff, Show ann) =>
Int -> View ann stuff -> ShowS
showsPrec :: Int -> View ann stuff -> ShowS
$cshow :: forall ann stuff.
(Show stuff, Show ann) =>
View ann stuff -> String
show :: View ann stuff -> String
$cshowList :: forall ann stuff.
(Show stuff, Show ann) =>
[View ann stuff] -> ShowS
showList :: [View ann stuff] -> ShowS
Show, (forall a b. (a -> b) -> View ann a -> View ann b)
-> (forall a b. a -> View ann b -> View ann a)
-> Functor (View ann)
forall a b. a -> View ann b -> View ann a
forall a b. (a -> b) -> View ann a -> View ann b
forall ann a b. a -> View ann b -> View ann a
forall ann a b. (a -> b) -> View ann a -> View ann b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall ann a b. (a -> b) -> View ann a -> View ann b
fmap :: forall a b. (a -> b) -> View ann a -> View ann b
$c<$ :: forall ann a b. a -> View ann b -> View ann a
<$ :: forall a b. a -> View ann b -> View ann a
Functor, (forall m. Monoid m => View ann m -> m)
-> (forall m a. Monoid m => (a -> m) -> View ann a -> m)
-> (forall m a. Monoid m => (a -> m) -> View ann a -> m)
-> (forall a b. (a -> b -> b) -> b -> View ann a -> b)
-> (forall a b. (a -> b -> b) -> b -> View ann a -> b)
-> (forall b a. (b -> a -> b) -> b -> View ann a -> b)
-> (forall b a. (b -> a -> b) -> b -> View ann a -> b)
-> (forall a. (a -> a -> a) -> View ann a -> a)
-> (forall a. (a -> a -> a) -> View ann a -> a)
-> (forall a. View ann a -> [a])
-> (forall a. View ann a -> Bool)
-> (forall a. View ann a -> Int)
-> (forall a. Eq a => a -> View ann a -> Bool)
-> (forall a. Ord a => View ann a -> a)
-> (forall a. Ord a => View ann a -> a)
-> (forall a. Num a => View ann a -> a)
-> (forall a. Num a => View ann a -> a)
-> Foldable (View ann)
forall a. Eq a => a -> View ann a -> Bool
forall a. Num a => View ann a -> a
forall a. Ord a => View ann a -> a
forall m. Monoid m => View ann m -> m
forall a. View ann a -> Bool
forall a. View ann a -> Int
forall a. View ann a -> [a]
forall a. (a -> a -> a) -> View ann a -> a
forall ann a. Eq a => a -> View ann a -> Bool
forall ann a. Num a => View ann a -> a
forall ann a. Ord a => View ann a -> a
forall m a. Monoid m => (a -> m) -> View ann a -> m
forall ann m. Monoid m => View ann m -> m
forall m a. Monoid m => (a -> m) -> View ann a -> m
forall ann a. View ann a -> Bool
forall ann a. View ann a -> Int
forall ann a. View ann a -> [a]
forall b a. (b -> a -> b) -> b -> View ann a -> b
forall a b. (a -> b -> b) -> b -> View ann a -> b
forall ann a. (a -> a -> a) -> View ann a -> a
forall ann m a. Monoid m => (a -> m) -> View ann a -> m
forall ann b a. (b -> a -> b) -> b -> View ann a -> b
forall ann a b. (a -> b -> b) -> b -> View ann a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
$cfold :: forall ann m. Monoid m => View ann m -> m
fold :: forall m. Monoid m => View ann m -> m
$cfoldMap :: forall ann m a. Monoid m => (a -> m) -> View ann a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> View ann a -> m
$cfoldMap' :: forall ann m a. Monoid m => (a -> m) -> View ann a -> m
foldMap' :: forall m a. Monoid m => (a -> m) -> View ann a -> m
$cfoldr :: forall ann a b. (a -> b -> b) -> b -> View ann a -> b
foldr :: forall a b. (a -> b -> b) -> b -> View ann a -> b
$cfoldr' :: forall ann a b. (a -> b -> b) -> b -> View ann a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> View ann a -> b
$cfoldl :: forall ann b a. (b -> a -> b) -> b -> View ann a -> b
foldl :: forall b a. (b -> a -> b) -> b -> View ann a -> b
$cfoldl' :: forall ann b a. (b -> a -> b) -> b -> View ann a -> b
foldl' :: forall b a. (b -> a -> b) -> b -> View ann a -> b
$cfoldr1 :: forall ann a. (a -> a -> a) -> View ann a -> a
foldr1 :: forall a. (a -> a -> a) -> View ann a -> a
$cfoldl1 :: forall ann a. (a -> a -> a) -> View ann a -> a
foldl1 :: forall a. (a -> a -> a) -> View ann a -> a
$ctoList :: forall ann a. View ann a -> [a]
toList :: forall a. View ann a -> [a]
$cnull :: forall ann a. View ann a -> Bool
null :: forall a. View ann a -> Bool
$clength :: forall ann a. View ann a -> Int
length :: forall a. View ann a -> Int
$celem :: forall ann a. Eq a => a -> View ann a -> Bool
elem :: forall a. Eq a => a -> View ann a -> Bool
$cmaximum :: forall ann a. Ord a => View ann a -> a
maximum :: forall a. Ord a => View ann a -> a
$cminimum :: forall ann a. Ord a => View ann a -> a
minimum :: forall a. Ord a => View ann a -> a
$csum :: forall ann a. Num a => View ann a -> a
sum :: forall a. Num a => View ann a -> a
$cproduct :: forall ann a. Num a => View ann a -> a
product :: forall a. Num a => View ann a -> a
Foldable, Functor (View ann)
Foldable (View ann)
(Functor (View ann), Foldable (View ann)) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> View ann a -> f (View ann b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    View ann (f a) -> f (View ann a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> View ann a -> m (View ann b))
-> (forall (m :: * -> *) a.
    Monad m =>
    View ann (m a) -> m (View ann a))
-> Traversable (View ann)
forall ann. Functor (View ann)
forall ann. Foldable (View ann)
forall ann (m :: * -> *) a.
Monad m =>
View ann (m a) -> m (View ann a)
forall ann (f :: * -> *) a.
Applicative f =>
View ann (f a) -> f (View ann a)
forall ann (m :: * -> *) a b.
Monad m =>
(a -> m b) -> View ann a -> m (View ann b)
forall ann (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> View ann a -> f (View ann b)
forall (t :: * -> *).
(Functor t, Foldable t) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a. Monad m => View ann (m a) -> m (View ann a)
forall (f :: * -> *) a.
Applicative f =>
View ann (f a) -> f (View ann a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> View ann a -> m (View ann b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> View ann a -> f (View ann b)
$ctraverse :: forall ann (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> View ann a -> f (View ann b)
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> View ann a -> f (View ann b)
$csequenceA :: forall ann (f :: * -> *) a.
Applicative f =>
View ann (f a) -> f (View ann a)
sequenceA :: forall (f :: * -> *) a.
Applicative f =>
View ann (f a) -> f (View ann a)
$cmapM :: forall ann (m :: * -> *) a b.
Monad m =>
(a -> m b) -> View ann a -> m (View ann b)
mapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> View ann a -> m (View ann b)
$csequence :: forall ann (m :: * -> *) a.
Monad m =>
View ann (m a) -> m (View ann a)
sequence :: forall (m :: * -> *) a. Monad m => View ann (m a) -> m (View ann a)
Traversable)

instance Bifunctor View where
  first :: forall a b c. (a -> b) -> View a c -> View b c
first a -> b
f = \case
    View{a
c
ann :: forall ann stuff. View ann stuff -> ann
stuff :: forall ann stuff. View ann stuff -> stuff
ann :: a
stuff :: c
..} -> View{ann :: b
ann = a -> b
f a
ann, c
stuff :: c
stuff :: c
stuff}
    Spacer{a
ann :: forall ann stuff. View ann stuff -> ann
ann :: a
..} -> Spacer{ann :: b
ann = a -> b
f a
ann}
    HStack{a
ann :: forall ann stuff. View ann stuff -> ann
ann :: a
ann, [View a c]
children :: forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View a c]
children} -> HStack{ann :: b
ann = a -> b
f a
ann, children :: [View b c]
children = (View a c -> View b c) -> [View a c] -> [View b c]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f) [View a c]
children}
    VStack{a
ann :: forall ann stuff. View ann stuff -> ann
ann :: a
ann, [View a c]
children :: forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View a c]
children} -> VStack{ann :: b
ann = a -> b
f a
ann, children :: [View b c]
children = (View a c -> View b c) -> [View a c] -> [View b c]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f) [View a c]
children}
    ZStack{a
ann :: forall ann stuff. View ann stuff -> ann
ann :: a
ann, [View a c]
children :: forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View a c]
children} -> ZStack{ann :: b
ann = a -> b
f a
ann, children :: [View b c]
children = (View a c -> View b c) -> [View a c] -> [View b c]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f) [View a c]
children}
    Overlay{a
ann :: forall ann stuff. View ann stuff -> ann
ann :: a
ann, View a c
primary :: forall ann stuff. View ann stuff -> View ann stuff
primary :: View a c
primary, View a c
secondary :: forall ann stuff. View ann stuff -> View ann stuff
secondary :: View a c
secondary} -> Overlay{ann :: b
ann = a -> b
f a
ann, primary :: View b c
primary = (a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f View a c
primary, secondary :: View b c
secondary = (a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f View a c
secondary}
    Frame{a
Vec2
Alignment
View a c
ann :: forall ann stuff. View ann stuff -> ann
size :: forall ann stuff. View ann stuff -> Vec2
align :: forall ann stuff. View ann stuff -> Alignment
inner :: forall ann stuff. View ann stuff -> View ann stuff
ann :: a
size :: Vec2
align :: Alignment
inner :: View a c
..} -> Frame{ann :: b
ann = a -> b
f a
ann, inner :: View b c
inner = (a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f View a c
inner, Vec2
Alignment
size :: Vec2
align :: Alignment
size :: Vec2
align :: Alignment
..}
    FlexibleFrame{a
Alignment
ViewSize
View a c
ann :: forall ann stuff. View ann stuff -> ann
align :: forall ann stuff. View ann stuff -> Alignment
inner :: forall ann stuff. View ann stuff -> View ann stuff
flex :: forall ann stuff. View ann stuff -> ViewSize
ann :: a
flex :: ViewSize
align :: Alignment
inner :: View a c
..} -> FlexibleFrame{ann :: b
ann = a -> b
f a
ann, inner :: View b c
inner = (a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f View a c
inner, Alignment
ViewSize
align :: Alignment
flex :: ViewSize
flex :: ViewSize
align :: Alignment
..}
    Padding{a
TRBL
View a c
ann :: forall ann stuff. View ann stuff -> ann
inner :: forall ann stuff. View ann stuff -> View ann stuff
trbl :: forall ann stuff. View ann stuff -> TRBL
ann :: a
trbl :: TRBL
inner :: View a c
..} -> Padding{ann :: b
ann = a -> b
f a
ann, inner :: View b c
inner = (a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f View a c
inner, TRBL
trbl :: TRBL
trbl :: TRBL
..}
    Offset{a
Vec2
View a c
ann :: forall ann stuff. View ann stuff -> ann
inner :: forall ann stuff. View ann stuff -> View ann stuff
xy :: forall ann stuff. View ann stuff -> Vec2
ann :: a
xy :: Vec2
inner :: View a c
..} -> Offset{ann :: b
ann = a -> b
f a
ann, inner :: View b c
inner = (a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f View a c
inner, Vec2
xy :: Vec2
xy :: Vec2
..}
    AspectRatio{a
Vec2
Alignment
View a c
ann :: forall ann stuff. View ann stuff -> ann
align :: forall ann stuff. View ann stuff -> Alignment
inner :: forall ann stuff. View ann stuff -> View ann stuff
aspect :: forall ann stuff. View ann stuff -> Vec2
ann :: a
aspect :: Vec2
align :: Alignment
inner :: View a c
..} -> AspectRatio{ann :: b
ann = a -> b
f a
ann, inner :: View b c
inner = (a -> b) -> View a c -> View b c
forall a b c. (a -> b) -> View a c -> View b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f View a c
inner, Vec2
Alignment
align :: Alignment
aspect :: Vec2
aspect :: Vec2
align :: Alignment
..}
  second :: forall b c a. (b -> c) -> View a b -> View a c
second = (b -> c) -> View a b -> View a c
forall a b. (a -> b) -> View a a -> View a b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap

-- ** Some shortcuts

view_ :: stuff -> View () stuff
view_ :: forall stuff. stuff -> View () stuff
view_ stuff
stuff = View{ann :: ()
ann=(), stuff
stuff :: stuff
stuff :: stuff
..}

spacer_ :: View () stuff
spacer_ :: forall stuff. View () stuff
spacer_ = Spacer{ann :: ()
ann=()}

-- *** Containers

hstack_ :: [View () stuff] -> View () stuff
hstack_ :: forall stuff. [View () stuff] -> View () stuff
hstack_ [View () stuff]
children = HStack{ann :: ()
ann=(), [View () stuff]
children :: [View () stuff]
children :: [View () stuff]
..}

vstack_ :: [View () stuff] -> View () stuff
vstack_ :: forall stuff. [View () stuff] -> View () stuff
vstack_ [View () stuff]
children = VStack{ann :: ()
ann=(), [View () stuff]
children :: [View () stuff]
children :: [View () stuff]
..}

zstack_ :: [View () stuff] -> View () stuff
zstack_ :: forall stuff. [View () stuff] -> View () stuff
zstack_ [View () stuff]
children = ZStack{ann :: ()
ann=(), [View () stuff]
children :: [View () stuff]
children :: [View () stuff]
..}

overlay_ :: View () stuff -> View () stuff -> View () stuff
overlay_ :: forall stuff. View () stuff -> View () stuff -> View () stuff
overlay_ View () stuff
secondary View () stuff
primary = Overlay{ann :: ()
ann=(), View () stuff
secondary :: View () stuff
primary :: View () stuff
secondary :: View () stuff
primary :: View () stuff
..}

-- *** Modifiers

frame_ :: Vec2 -> View () stuff -> View () stuff
frame_ :: forall stuff. Vec2 -> View () stuff -> View () stuff
frame_ Vec2
size View () stuff
inner = Frame{ann :: ()
ann=(), align :: Alignment
align = Alignment
Alignment.center, Vec2
View () stuff
size :: Vec2
inner :: View () stuff
size :: Vec2
inner :: View () stuff
..}

flexible_ :: ViewSize -> Alignment -> View () stuff -> View () stuff
flexible_ :: forall stuff.
ViewSize -> Alignment -> View () stuff -> View () stuff
flexible_ ViewSize
flex Alignment
align View () stuff
inner = FlexibleFrame{ann :: ()
ann=(), Alignment
ViewSize
View () stuff
align :: Alignment
inner :: View () stuff
flex :: ViewSize
flex :: ViewSize
align :: Alignment
inner :: View () stuff
..}

aspect_ :: Vec2 -> View () stuff -> View () stuff
aspect_ :: forall stuff. Vec2 -> View () stuff -> View () stuff
aspect_ Vec2
ratio View () stuff
inner = AspectRatio{ann :: ()
ann=(), aspect :: Vec2
aspect=Vec2
ratio, align :: Alignment
align=Alignment
Alignment.center, View () stuff
inner :: View () stuff
inner :: View () stuff
..}

padding_ :: Vec4 -> View () stuff -> View () stuff
padding_ :: forall stuff. Vec4 -> View () stuff -> View () stuff
padding_ Vec4
trbl View () stuff
inner = Padding{ann :: ()
ann=(), trbl :: TRBL
trbl=Vec4 -> TRBL
Box.TRBL Vec4
trbl, View () stuff
inner :: View () stuff
inner :: View () stuff
..}

offset_ :: Vec2 -> View () stuff -> View () stuff
offset_ :: forall stuff. Vec2 -> View () stuff -> View () stuff
offset_ Vec2
xy View () stuff
inner = Offset{ann :: ()
ann=(), Vec2
View () stuff
inner :: View () stuff
xy :: Vec2
xy :: Vec2
inner :: View () stuff
..}

-- * Flexibility helper

-- | Represents size constraints and flexibility for a layout node.
data ViewSize = ViewSize
  { ViewSize -> Maybe Float
minWidth, ViewSize -> Maybe Float
maxWidth
  , ViewSize -> Maybe Float
minHeight, ViewSize -> Maybe Float
maxHeight :: Maybe Float
  -- XXX: put ideal size here?
  } deriving (ViewSize -> ViewSize -> Bool
(ViewSize -> ViewSize -> Bool)
-> (ViewSize -> ViewSize -> Bool) -> Eq ViewSize
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ViewSize -> ViewSize -> Bool
== :: ViewSize -> ViewSize -> Bool
$c/= :: ViewSize -> ViewSize -> Bool
/= :: ViewSize -> ViewSize -> Bool
Eq, Int -> ViewSize -> ShowS
[ViewSize] -> ShowS
ViewSize -> String
(Int -> ViewSize -> ShowS)
-> (ViewSize -> String) -> ([ViewSize] -> ShowS) -> Show ViewSize
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ViewSize -> ShowS
showsPrec :: Int -> ViewSize -> ShowS
$cshow :: ViewSize -> String
show :: ViewSize -> String
$cshowList :: [ViewSize] -> ShowS
showList :: [ViewSize] -> ShowS
Show)

-- | Creates a ViewSize for a fixed-size view.
fixed_ :: Vec2 -> ViewSize
fixed_ :: Vec2 -> ViewSize
fixed_ Vec2
size =
  Vec2 -> (Float -> Float -> ViewSize) -> ViewSize
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
size \Float
w Float
h ->
    ViewSize
      { minWidth :: Maybe Float
minWidth = Float -> Maybe Float
forall a. a -> Maybe a
Just Float
w
      , maxWidth :: Maybe Float
maxWidth = Float -> Maybe Float
forall a. a -> Maybe a
Just Float
w
      , minHeight :: Maybe Float
minHeight = Float -> Maybe Float
forall a. a -> Maybe a
Just Float
h
      , maxHeight :: Maybe Float
maxHeight = Float -> Maybe Float
forall a. a -> Maybe a
Just Float
h
      }

-- | Creates a ViewSize for a fully flexible view.
infinite_ :: ViewSize
infinite_ :: ViewSize
infinite_ = ViewSize
  { minWidth :: Maybe Float
minWidth = Float -> Maybe Float
forall a. a -> Maybe a
Just Float
0
  , maxWidth :: Maybe Float
maxWidth = Float -> Maybe Float
forall a. a -> Maybe a
Just Float
inf
  , minHeight :: Maybe Float
minHeight = Float -> Maybe Float
forall a. a -> Maybe a
Just Float
0
  , maxHeight :: Maybe Float
maxHeight = Float -> Maybe Float
forall a. a -> Maybe a
Just Float
inf
  }

range_ :: Vec2 -> Vec2 -> ViewSize
range_ :: Vec2 -> Vec2 -> ViewSize
range_ Vec2
a Vec2
b =
  Vec2 -> (Float -> Float -> ViewSize) -> ViewSize
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
a \Float
aw Float
ah ->
    Vec2 -> (Float -> Float -> ViewSize) -> ViewSize
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
b \Float
bw Float
bh ->
      ViewSize
        { minWidth :: Maybe Float
minWidth = Float -> Maybe Float
forall a. a -> Maybe a
Just (Float -> Maybe Float) -> Float -> Maybe Float
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
forall a. Ord a => a -> a -> a
min Float
aw Float
bw
        , maxWidth :: Maybe Float
maxWidth = Float -> Maybe Float
forall a. a -> Maybe a
Just (Float -> Maybe Float) -> Float -> Maybe Float
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
forall a. Ord a => a -> a -> a
max Float
aw Float
bw
        , minHeight :: Maybe Float
minHeight = Float -> Maybe Float
forall a. a -> Maybe a
Just (Float -> Maybe Float) -> Float -> Maybe Float
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
forall a. Ord a => a -> a -> a
min Float
ah Float
bh
        , maxHeight :: Maybe Float
maxHeight = Float -> Maybe Float
forall a. a -> Maybe a
Just (Float -> Maybe Float) -> Float -> Maybe Float
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float
forall a. Ord a => a -> a -> a
max Float
ah Float
bh
        }

-- | Creates a ViewSize that reports parent size
parent_ :: ViewSize
parent_ :: ViewSize
parent_ = ViewSize
  { minWidth :: Maybe Float
minWidth = Maybe Float
forall a. Maybe a
Nothing
  , maxWidth :: Maybe Float
maxWidth = Maybe Float
forall a. Maybe a
Nothing
  , minHeight :: Maybe Float
minHeight = Maybe Float
forall a. Maybe a
Nothing
  , maxHeight :: Maybe Float
maxHeight = Maybe Float
forall a. Maybe a
Nothing
  }

parentWidth :: ViewSize -> ViewSize
parentWidth :: ViewSize -> ViewSize
parentWidth ViewSize
a = ViewSize
a {minWidth = Nothing, maxWidth = Nothing}

parentHeight :: ViewSize -> ViewSize
parentHeight :: ViewSize -> ViewSize
parentHeight ViewSize
a = ViewSize
a {minHeight = Nothing, maxHeight = Nothing}

-- * Layout steps

-- | Measurement pre-pass
measure :: LayoutView stuff => View () stuff -> View ViewSize stuff
measure :: forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure = \case
  View {stuff
stuff :: forall ann stuff. View ann stuff -> stuff
stuff :: stuff
stuff} -> View{ann :: ViewSize
ann=stuff -> ViewSize
forall stuff. LayoutView stuff => stuff -> ViewSize
viewFlexibility stuff
stuff, stuff
stuff :: stuff
stuff :: stuff
stuff}
  Spacer{} -> Spacer{ann :: ViewSize
ann=ViewSize
infinite_}
  Frame{()
Vec2
Alignment
View () stuff
ann :: forall ann stuff. View ann stuff -> ann
size :: forall ann stuff. View ann stuff -> Vec2
align :: forall ann stuff. View ann stuff -> Alignment
inner :: forall ann stuff. View ann stuff -> View ann stuff
ann :: ()
size :: Vec2
align :: Alignment
inner :: View () stuff
..} -> Frame{ann :: ViewSize
ann=Vec2 -> ViewSize
fixed_ Vec2
size, inner :: View ViewSize stuff
inner=View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure View () stuff
inner, Vec2
Alignment
size :: Vec2
align :: Alignment
size :: Vec2
align :: Alignment
..}
  FlexibleFrame{()
Alignment
ViewSize
View () stuff
ann :: forall ann stuff. View ann stuff -> ann
align :: forall ann stuff. View ann stuff -> Alignment
inner :: forall ann stuff. View ann stuff -> View ann stuff
flex :: forall ann stuff. View ann stuff -> ViewSize
ann :: ()
flex :: ViewSize
align :: Alignment
inner :: View () stuff
..} -> FlexibleFrame{ann :: ViewSize
ann=ViewSize
flex', inner :: View ViewSize stuff
inner=View ViewSize stuff
inner', Alignment
ViewSize
align :: Alignment
flex :: ViewSize
flex :: ViewSize
align :: Alignment
..}
    where
      inner' :: View ViewSize stuff
inner' = View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure View () stuff
inner
      innerFlex :: ViewSize
innerFlex = View ViewSize stuff
inner'.ann
      flex' :: ViewSize
flex' = ViewSize -- intersection of flexibility ranges
        { minWidth :: Maybe Float
minWidth = Float -> Float -> Float
forall a. Ord a => a -> a -> a
max (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ViewSize
flex.minWidth Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ViewSize
innerFlex.minWidth
        , maxWidth :: Maybe Float
maxWidth = Float -> Float -> Float
forall a. Ord a => a -> a -> a
min (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ViewSize
flex.maxWidth Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ViewSize
innerFlex.maxWidth
        , minHeight :: Maybe Float
minHeight = Float -> Float -> Float
forall a. Ord a => a -> a -> a
max (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ViewSize
flex.minHeight Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ViewSize
innerFlex.minHeight
        , maxHeight :: Maybe Float
maxHeight = Float -> Float -> Float
forall a. Ord a => a -> a -> a
min (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ViewSize
flex.maxHeight Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ViewSize
innerFlex.maxHeight
        }
  Padding{()
TRBL
View () stuff
ann :: forall ann stuff. View ann stuff -> ann
inner :: forall ann stuff. View ann stuff -> View ann stuff
trbl :: forall ann stuff. View ann stuff -> TRBL
ann :: ()
trbl :: TRBL
inner :: View () stuff
..} -> Padding{ann :: ViewSize
ann=ViewSize
expanded, inner :: View ViewSize stuff
inner=View ViewSize stuff
inner', TRBL
trbl :: TRBL
trbl :: TRBL
..}
    where
      inner' :: View ViewSize stuff
inner' = View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure View () stuff
inner
      innerFlex :: ViewSize
innerFlex = View ViewSize stuff
inner'.ann
      expanded :: ViewSize
expanded = Vec4 -> (Float -> Float -> Float -> Float -> ViewSize) -> ViewSize
forall r. Vec4 -> (Float -> Float -> Float -> Float -> r) -> r
withVec4 Vec4
trbl4 \Float
t Float
r Float
b Float
l -> ViewSize
innerFlex
        { minWidth = (+ (l + r)) <$> innerFlex.minWidth
        , minHeight = (+ (t + b)) <$> innerFlex.minHeight
        }
      Box.TRBL Vec4
trbl4 = TRBL
trbl
  Offset{()
Vec2
View () stuff
ann :: forall ann stuff. View ann stuff -> ann
inner :: forall ann stuff. View ann stuff -> View ann stuff
xy :: forall ann stuff. View ann stuff -> Vec2
ann :: ()
xy :: Vec2
inner :: View () stuff
..} -> Offset{ann :: ViewSize
ann=View ViewSize stuff
inner'.ann, inner :: View ViewSize stuff
inner=View ViewSize stuff
inner', Vec2
xy :: Vec2
xy :: Vec2
..}
    where
      inner' :: View ViewSize stuff
inner' = View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure View () stuff
inner
  AspectRatio{()
Vec2
Alignment
View () stuff
ann :: forall ann stuff. View ann stuff -> ann
align :: forall ann stuff. View ann stuff -> Alignment
inner :: forall ann stuff. View ann stuff -> View ann stuff
aspect :: forall ann stuff. View ann stuff -> Vec2
ann :: ()
aspect :: Vec2
align :: Alignment
inner :: View () stuff
..} -> AspectRatio{ann :: ViewSize
ann=ViewSize
ann', inner :: View ViewSize stuff
inner=View ViewSize stuff
inner', Vec2
Alignment
align :: Alignment
aspect :: Vec2
aspect :: Vec2
align :: Alignment
..}
    where
      ann' :: ViewSize
ann' = View ViewSize stuff
inner'.ann -- XXX: pass-through?
      inner' :: View ViewSize stuff
inner' = View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure View () stuff
inner
  HStack{[View () stuff]
children :: forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View () stuff]
children} -> HStack{ann :: ViewSize
ann=ViewSize
stackViewSize, children :: [View ViewSize stuff]
children=[View ViewSize stuff]
measured}
    where
      measured :: [View ViewSize stuff]
measured = (View () stuff -> View ViewSize stuff)
-> [View () stuff] -> [View ViewSize stuff]
forall a b. (a -> b) -> [a] -> [b]
map View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure [View () stuff]
children
      stackViewSize :: ViewSize
stackViewSize = (ViewSize -> View ViewSize stuff -> ViewSize)
-> ViewSize -> [View ViewSize stuff] -> ViewSize
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\ViewSize
vs -> ViewSize -> ViewSize -> ViewSize
forall {r} {r}.
(HasField "minWidth" r (Maybe Float),
 HasField "minWidth" r (Maybe Float),
 HasField "maxWidth" r (Maybe Float),
 HasField "maxWidth" r (Maybe Float),
 HasField "minHeight" r (Maybe Float),
 HasField "minHeight" r (Maybe Float),
 HasField "maxHeight" r (Maybe Float),
 HasField "maxHeight" r (Maybe Float)) =>
r -> r -> ViewSize
stackViewSize' ViewSize
vs (ViewSize -> ViewSize)
-> (View ViewSize stuff -> ViewSize)
-> View ViewSize stuff
-> ViewSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. View ViewSize stuff -> ViewSize
forall ann stuff. View ann stuff -> ann
ann) (Vec2 -> ViewSize
fixed_ Vec2
0) [View ViewSize stuff]
measured
      stackViewSize' :: r -> r -> ViewSize
stackViewSize' r
a r
b = ViewSize
        { minWidth :: Maybe Float
minWidth = Float -> Float -> Float
forall a. Num a => a -> a -> a
(+) (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.minWidth Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.minWidth -- combined horizontal flex
        , maxWidth :: Maybe Float
maxWidth = Float -> Float -> Float
forall a. Num a => a -> a -> a
(+) (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.maxWidth Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.maxWidth
        , minHeight :: Maybe Float
minHeight = Float -> Float -> Float
forall a. Ord a => a -> a -> a
max (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.minHeight Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.minHeight -- intersection of vertical flex
        , maxHeight :: Maybe Float
maxHeight = Float -> Float -> Float
forall a. Ord a => a -> a -> a
min (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.maxHeight Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.maxHeight
        }
  VStack{[View () stuff]
children :: forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View () stuff]
children} -> VStack{ann :: ViewSize
ann=ViewSize
stackViewSize, children :: [View ViewSize stuff]
children=[View ViewSize stuff]
measured}
    where
      measured :: [View ViewSize stuff]
measured = (View () stuff -> View ViewSize stuff)
-> [View () stuff] -> [View ViewSize stuff]
forall a b. (a -> b) -> [a] -> [b]
map View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure [View () stuff]
children
      stackViewSize :: ViewSize
stackViewSize = (ViewSize -> View ViewSize stuff -> ViewSize)
-> ViewSize -> [View ViewSize stuff] -> ViewSize
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\ViewSize
vs -> ViewSize -> ViewSize -> ViewSize
forall {r} {r}.
(HasField "minWidth" r (Maybe Float),
 HasField "minWidth" r (Maybe Float),
 HasField "maxWidth" r (Maybe Float),
 HasField "maxWidth" r (Maybe Float),
 HasField "minHeight" r (Maybe Float),
 HasField "minHeight" r (Maybe Float),
 HasField "maxHeight" r (Maybe Float),
 HasField "maxHeight" r (Maybe Float)) =>
r -> r -> ViewSize
stackViewSize' ViewSize
vs (ViewSize -> ViewSize)
-> (View ViewSize stuff -> ViewSize)
-> View ViewSize stuff
-> ViewSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. View ViewSize stuff -> ViewSize
forall ann stuff. View ann stuff -> ann
ann) (Vec2 -> ViewSize
fixed_ Vec2
0) [View ViewSize stuff]
measured
      stackViewSize' :: r -> r -> ViewSize
stackViewSize' r
a r
b = ViewSize
        { minWidth :: Maybe Float
minWidth = Float -> Float -> Float
forall a. Ord a => a -> a -> a
max (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.minWidth Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.minWidth -- intersection of horizontal flex
        , maxWidth :: Maybe Float
maxWidth = Float -> Float -> Float
forall a. Ord a => a -> a -> a
min (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.maxWidth Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.maxWidth
        , minHeight :: Maybe Float
minHeight = Float -> Float -> Float
forall a. Num a => a -> a -> a
(+) (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.minHeight Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.minHeight --  combined vertical flex
        , maxHeight :: Maybe Float
maxHeight = Float -> Float -> Float
forall a. Num a => a -> a -> a
(+) (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.maxHeight Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.maxHeight
        }
  ZStack{[View () stuff]
children :: forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View () stuff]
children} -> ZStack{ann :: ViewSize
ann=ViewSize
stackViewSize, children :: [View ViewSize stuff]
children=[View ViewSize stuff]
measured}
    where
      measured :: [View ViewSize stuff]
measured = (View () stuff -> View ViewSize stuff)
-> [View () stuff] -> [View ViewSize stuff]
forall a b. (a -> b) -> [a] -> [b]
map View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure [View () stuff]
children
      stackViewSize :: ViewSize
stackViewSize = (ViewSize -> View ViewSize stuff -> ViewSize)
-> ViewSize -> [View ViewSize stuff] -> ViewSize
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\ViewSize
vs -> ViewSize -> ViewSize -> ViewSize
forall {r} {r}.
(HasField "minWidth" r (Maybe Float),
 HasField "minWidth" r (Maybe Float),
 HasField "maxWidth" r (Maybe Float),
 HasField "maxWidth" r (Maybe Float),
 HasField "minHeight" r (Maybe Float),
 HasField "minHeight" r (Maybe Float),
 HasField "maxHeight" r (Maybe Float),
 HasField "maxHeight" r (Maybe Float)) =>
r -> r -> ViewSize
stackViewSize' ViewSize
vs (ViewSize -> ViewSize)
-> (View ViewSize stuff -> ViewSize)
-> View ViewSize stuff
-> ViewSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. View ViewSize stuff -> ViewSize
forall ann stuff. View ann stuff -> ann
ann) (Vec2 -> ViewSize
fixed_ Vec2
0) [View ViewSize stuff]
measured
      stackViewSize' :: r -> r -> ViewSize
stackViewSize' r
a r
b = ViewSize
        { minWidth :: Maybe Float
minWidth = Float -> Float -> Float
forall a. Ord a => a -> a -> a
max (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.minWidth Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.minWidth -- intersection of horizontal flex
        , maxWidth :: Maybe Float
maxWidth = Float -> Float -> Float
forall a. Ord a => a -> a -> a
min (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.maxWidth Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.maxWidth
        , minHeight :: Maybe Float
minHeight = Float -> Float -> Float
forall a. Ord a => a -> a -> a
max (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.minHeight Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.minHeight --  intersection of vertical flex
        , maxHeight :: Maybe Float
maxHeight = Float -> Float -> Float
forall a. Ord a => a -> a -> a
min (Float -> Float -> Float) -> Maybe Float -> Maybe (Float -> Float)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r
a.maxHeight Maybe (Float -> Float) -> Maybe Float -> Maybe Float
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> r
b.maxHeight
        }
  Overlay{View () stuff
primary :: forall ann stuff. View ann stuff -> View ann stuff
primary :: View () stuff
primary, View () stuff
secondary :: forall ann stuff. View ann stuff -> View ann stuff
secondary :: View () stuff
secondary} -> Overlay{ann :: ViewSize
ann=View ViewSize stuff
primary'.ann, primary :: View ViewSize stuff
primary=View ViewSize stuff
primary', secondary :: View ViewSize stuff
secondary=View ViewSize stuff
secondary'}
    where
      primary' :: View ViewSize stuff
primary' = View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure View () stuff
primary -- pass-through wrt primary measurements
      secondary' :: View ViewSize stuff
secondary' = View () stuff -> View ViewSize stuff
forall stuff.
LayoutView stuff =>
View () stuff -> View ViewSize stuff
measure View () stuff
secondary -- ignore secondary flex

-- | Run the propose-report-place protocol on a flex-measured view tree
place :: LayoutView stuff => Box -> View ViewSize stuff -> View Box (Placed stuff)
place :: forall stuff.
LayoutView stuff =>
Box -> View ViewSize stuff -> View Box (Placed stuff)
place Box
parent View ViewSize stuff
element = (Vec2, Box -> View Box (Placed stuff))
-> Box -> View Box (Placed stuff)
forall a b. (a, b) -> b
snd (Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend Box
parent.size View ViewSize stuff
element) Box
parent

-- | Propose-Report-Place protocol using continuations
--
-- Inner children can't be placed until the whole propose-report dance finishes.
suspend
  :: forall stuff
  .  LayoutView stuff
  => Vec2
  -> View ViewSize stuff
  -> (Vec2, Box -> View Box (Placed stuff))
suspend :: forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend Vec2
proposed = \case
  Spacer{} ->
    ( Vec2
proposed -- report the proposed
    , \Box
placed -> Spacer{ann :: Box
ann=Box
placed} -- keep the placed
    )
  View{stuff
stuff :: forall ann stuff. View ann stuff -> stuff
stuff :: stuff
stuff} ->
    ( Vec2
reported -- report dynamic size
    , \Box
placed ->
        View
          { ann :: Box
ann = Box
placed
          , stuff :: Placed stuff
stuff = forall stuff.
LayoutView stuff =>
Box -> ReportedCache stuff -> Placed stuff
placeView @stuff Box
placed ReportedCache stuff
cache -- instantiate the placed view
          }
    )
    where
      (Vec2
reported, ReportedCache stuff
cache) = Vec2 -> stuff -> (Vec2, ReportedCache stuff)
forall stuff.
LayoutView stuff =>
Vec2 -> stuff -> (Vec2, ReportedCache stuff)
proposeView Vec2
proposed stuff
stuff
  Frame{Vec2
Alignment
ViewSize
View ViewSize stuff
ann :: forall ann stuff. View ann stuff -> ann
size :: forall ann stuff. View ann stuff -> Vec2
align :: forall ann stuff. View ann stuff -> Alignment
inner :: forall ann stuff. View ann stuff -> View ann stuff
ann :: ViewSize
size :: Vec2
align :: Alignment
inner :: View ViewSize stuff
..} ->
    ( Vec2
size -- frame reports its size right away
    , \Box
placedFrame ->
        Frame
          { ann :: Box
ann = Box
placedFrame -- keep the placed for itself
          , inner :: View Box (Placed stuff)
inner =
              let
                -- now that the frame has its own box, it can properly place its contents
                innerBox :: Box
innerBox = Alignment -> Vec2 -> Box -> Box
Layout.placeSize Alignment
align Vec2
reported Box
placedFrame
              in
                -- and resolve the continuation
                Box -> View Box (Placed stuff)
suspended Box
innerBox
          , Vec2
Alignment
size :: Vec2
align :: Alignment
size :: Vec2
align :: Alignment
..
          }
    )
    where
      (Vec2
reported, Box -> View Box (Placed stuff)
suspended) = Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend Vec2
size View ViewSize stuff
inner -- frame proposes its size
  FlexibleFrame{Alignment
ViewSize
View ViewSize stuff
ann :: forall ann stuff. View ann stuff -> ann
align :: forall ann stuff. View ann stuff -> Alignment
inner :: forall ann stuff. View ann stuff -> View ann stuff
flex :: forall ann stuff. View ann stuff -> ViewSize
ann :: ViewSize
flex :: ViewSize
align :: Alignment
inner :: View ViewSize stuff
..} ->
    ( Vec2 -> ViewSize -> Vec2 -> Vec2
vsClamp Vec2
proposed ViewSize
flex Vec2
reported -- reports clamped to self, while defaulting to parent
    , \Box
placed ->
        let
          innerBox :: Box
innerBox = Alignment -> Vec2 -> Box -> Box
Layout.placeSize Alignment
align Vec2
reported Box
placed
        in
          FlexibleFrame
            { ann :: Box
ann = Box
placed
            , inner :: View Box (Placed stuff)
inner = Box -> View Box (Placed stuff)
suspended Box
innerBox
            , Alignment
ViewSize
align :: Alignment
flex :: ViewSize
flex :: ViewSize
align :: Alignment
..
            }
    )
    where
      -- proposes clamped parent
      (Vec2
reported, Box -> View Box (Placed stuff)
suspended) = Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend (Vec2 -> ViewSize -> Vec2 -> Vec2
vsClamp Vec2
proposed ViewSize
flex Vec2
proposed) View ViewSize stuff
inner
  Padding{TRBL
ViewSize
View ViewSize stuff
ann :: forall ann stuff. View ann stuff -> ann
inner :: forall ann stuff. View ann stuff -> View ann stuff
trbl :: forall ann stuff. View ann stuff -> TRBL
ann :: ViewSize
trbl :: TRBL
inner :: View ViewSize stuff
..} ->
    ( Vec2
reported Vec2 -> Vec2 -> Vec2
forall a. Num a => a -> a -> a
+ Vec2
pads
    , \Box
placed ->
        let
          innerBox :: Box
innerBox = TRBL -> Box -> Box
Box.addPadding TRBL
trbl Box
placed
        in
        Padding
          { ann :: Box
ann = Box
placed
          , inner :: View Box (Placed stuff)
inner = Box -> View Box (Placed stuff)
suspended Box
innerBox
          , TRBL
trbl :: TRBL
trbl :: TRBL
..
          }
    )
    where
      (Vec2
reported, Box -> View Box (Placed stuff)
suspended) = Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend (Vec2
proposed Vec2 -> Vec2 -> Vec2
forall a. Num a => a -> a -> a
- Vec2
pads) View ViewSize stuff
inner
      pads :: Vec2
pads = Vec4 -> (Float -> Float -> Float -> Float -> Vec2) -> Vec2
forall r. Vec4 -> (Float -> Float -> Float -> Float -> r) -> r
withVec4 Vec4
trbl4 \Float
t Float
r Float
b Float
l -> Float -> Float -> Vec2
vec2 (Float
l Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
r) (Float
t Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
b)
      Box.TRBL Vec4
trbl4 = TRBL
trbl
  Offset{Vec2
ViewSize
View ViewSize stuff
ann :: forall ann stuff. View ann stuff -> ann
inner :: forall ann stuff. View ann stuff -> View ann stuff
xy :: forall ann stuff. View ann stuff -> Vec2
ann :: ViewSize
xy :: Vec2
inner :: View ViewSize stuff
..} ->
    ( Vec2
reported
    , \Box
placed -> Offset
        { ann :: Box
ann = Box
placed
        , inner :: View Box (Placed stuff)
inner = Box -> View Box (Placed stuff)
suspended (Box -> View Box (Placed stuff)) -> Box -> View Box (Placed stuff)
forall a b. (a -> b) -> a -> b
$ Vec2 -> Box -> Box
Box.move Vec2
xy Box
placed
        , Vec2
xy :: Vec2
xy :: Vec2
..
        }
    )
    where
      (Vec2
reported, Box -> View Box (Placed stuff)
suspended) = Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend Vec2
proposed View ViewSize stuff
inner
  AspectRatio{Vec2
Alignment
ViewSize
View ViewSize stuff
ann :: forall ann stuff. View ann stuff -> ann
align :: forall ann stuff. View ann stuff -> Alignment
inner :: forall ann stuff. View ann stuff -> View ann stuff
aspect :: forall ann stuff. View ann stuff -> Vec2
ann :: ViewSize
aspect :: Vec2
align :: Alignment
inner :: View ViewSize stuff
..} ->
    ( Vec2
reported
    , \Box
placed ->
        let
          innerBox :: Box
innerBox = Alignment -> Vec2 -> Box -> Box
Layout.placeSize Alignment
align Vec2
reported Box
placed
        in
        AspectRatio
          { ann :: Box
ann = Box
placed
          , inner :: View Box (Placed stuff)
inner = Box -> View Box (Placed stuff)
suspended Box
innerBox
          , Vec2
Alignment
align :: Alignment
aspect :: Vec2
aspect :: Vec2
align :: Alignment
..
          }
    )
    where
      -- 1. query direct size, ignore suspended
      probed :: Vec2
probed = (Vec2, Box -> View Box (Placed stuff)) -> Vec2
forall a b. (a, b) -> a
fst ((Vec2, Box -> View Box (Placed stuff)) -> Vec2)
-> (Vec2, Box -> View Box (Placed stuff)) -> Vec2
forall a b. (a -> b) -> a -> b
$ Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend (Vec2
aspect Vec2 -> Float -> Vec2
forall v a. VectorSpace v a => v -> a -> v
^* Vec2 -> Float
scale Vec2
proposed) View ViewSize stuff
inner
      -- 2. re-query with the fit size
      (Vec2
reported, Box -> View Box (Placed stuff)
suspended) = Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend (Vec2
aspect Vec2 -> Float -> Vec2
forall v a. VectorSpace v a => v -> a -> v
^* Vec2 -> Float
scale Vec2
probed) View ViewSize stuff
inner
      scale :: Vec2 -> Float
scale Vec2
p =
        Vec2 -> (Float -> Float -> Float) -> Float
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
aspect \Float
aw Float
ah ->
          Vec2 -> (Float -> Float -> Float) -> Float
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
p \Float
pw Float
ph ->
            if Float
pw Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
ph Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
aw Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
ah then
              Float
ph Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
ah
            else
              Float
pw Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
aw
  HStack{[View ViewSize stuff]
children :: forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View ViewSize stuff]
children} ->
    -- Like the Frame, but operating on multiple elements
    ( (Vec2 -> Vec2 -> Vec2) -> Vec2 -> [Vec2] -> Vec2
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Vec2 -> Vec2 -> Vec2
combineH Vec2
0 ([Vec2] -> Vec2) -> [Vec2] -> Vec2
forall a b. (a -> b) -> a -> b
$ ((Vec2, Box -> View Box (Placed stuff)) -> Vec2)
-> [(Vec2, Box -> View Box (Placed stuff))] -> [Vec2]
forall a b. (a -> b) -> [a] -> [b]
map (Vec2, Box -> View Box (Placed stuff)) -> Vec2
forall a b. (a, b) -> a
fst [(Vec2, Box -> View Box (Placed stuff))]
children' -- stack reports the combined size of its children reports
    , \Box
placedStack ->
        let
          placedChildren :: [View Box (Placed stuff)]
          placedChildren :: [View Box (Placed stuff)]
placedChildren = (Box, [View Box (Placed stuff)]) -> [View Box (Placed stuff)]
forall a b. (a, b) -> b
snd ((Box, [View Box (Placed stuff)]) -> [View Box (Placed stuff)])
-> (Box, [View Box (Placed stuff)]) -> [View Box (Placed stuff)]
forall a b. (a -> b) -> a -> b
$ (Box
 -> (Vec2, Box -> View Box (Placed stuff))
 -> (Box, View Box (Placed stuff)))
-> Box
-> [(Vec2, Box -> View Box (Placed stuff))]
-> (Box, [View Box (Placed stuff)])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL Box
-> (Vec2, Box -> View Box (Placed stuff))
-> (Box, View Box (Placed stuff))
placeLeftToRight Box
placedStack [(Vec2, Box -> View Box (Placed stuff))]
children'
            where
              placeLeftToRight :: Box -> (Vec2, Box -> View Box (Placed stuff)) -> (Box, View Box (Placed stuff))
              placeLeftToRight :: Box
-> (Vec2, Box -> View Box (Placed stuff))
-> (Box, View Box (Placed stuff))
placeLeftToRight Box
remaining (Vec2
reportedSize, Box -> View Box (Placed stuff)
suspended) =
                ( Box
remaining'
                , Box -> View Box (Placed stuff)
suspended Box
placed
                )
                where
                  (Box
slot, Box
remaining') = Vec2 -> (Float -> Float -> (Box, Box)) -> (Box, Box)
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
reportedSize \Float
w Float
_h -> Float -> Box -> (Box, Box)
Layout.cutLeft Float
w Box
remaining
                  placed :: Box
placed = Alignment -> Vec2 -> Box -> Box
Layout.placeSize Alignment
Alignment.center Vec2
reportedSize Box
slot
        in
          HStack
            { ann :: Box
ann = Box
-> (NonEmpty (View Box (Placed stuff)) -> Box)
-> Maybe (NonEmpty (View Box (Placed stuff)))
-> Box
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Box
placedStack ((View Box (Placed stuff) -> Box)
-> NonEmpty (View Box (Placed stuff)) -> Box
forall m a. Semigroup m => (a -> m) -> NonEmpty a -> m
forall (t :: * -> *) m a.
(Foldable1 t, Semigroup m) =>
(a -> m) -> t a -> m
foldMap1' View Box (Placed stuff) -> Box
forall ann stuff. View ann stuff -> ann
ann) (Maybe (NonEmpty (View Box (Placed stuff))) -> Box)
-> Maybe (NonEmpty (View Box (Placed stuff))) -> Box
forall a b. (a -> b) -> a -> b
$ [View Box (Placed stuff)]
-> Maybe (NonEmpty (View Box (Placed stuff)))
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty [View Box (Placed stuff)]
placedChildren
            , children :: [View Box (Placed stuff)]
children = [View Box (Placed stuff)]
placedChildren
            }
    )
    where
      -- | Record index, sort by flexibility, process, restore order
      children' :: [(Vec2, Box -> View Box (Placed stuff))]
children' =
        Array Int (Vec2, Box -> View Box (Placed stuff))
-> [(Vec2, Box -> View Box (Placed stuff))]
forall a. Array Int a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Array Int (Vec2, Box -> View Box (Placed stuff))
 -> [(Vec2, Box -> View Box (Placed stuff))])
-> ([(Int, (Vec2, Box -> View Box (Placed stuff)))]
    -> Array Int (Vec2, Box -> View Box (Placed stuff)))
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
-> [(Vec2, Box -> View Box (Placed stuff))]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int)
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
-> Array Int (Vec2, Box -> View Box (Placed stuff))
forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (Int
0, Int
numChildren Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) ([(Int, (Vec2, Box -> View Box (Placed stuff)))]
 -> [(Vec2, Box -> View Box (Placed stuff))])
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
-> [(Vec2, Box -> View Box (Placed stuff))]
forall a b. (a -> b) -> a -> b
$
          ((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
forall a b. (a, b) -> b
snd (((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
 -> [(Int, (Vec2, Box -> View Box (Placed stuff)))])
-> ((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
forall a b. (a -> b) -> a -> b
$ ((Float, Vec2)
 -> (Int, View ViewSize stuff)
 -> ((Float, Vec2), (Int, (Vec2, Box -> View Box (Placed stuff)))))
-> (Float, Vec2)
-> [(Int, View ViewSize stuff)]
-> ((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL (Float, Vec2)
-> (Int, View ViewSize stuff)
-> ((Float, Vec2), (Int, (Vec2, Box -> View Box (Placed stuff))))
forall {stuff} {a}.
LayoutView stuff =>
(Float, Vec2)
-> (a, View ViewSize stuff)
-> ((Float, Vec2), (a, (Vec2, Box -> View Box (Placed stuff))))
f (Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
numChildren, Vec2
proposed) ([(Int, View ViewSize stuff)]
 -> ((Float, Vec2),
     [(Int, (Vec2, Box -> View Box (Placed stuff)))]))
-> [(Int, View ViewSize stuff)]
-> ((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
forall a b. (a -> b) -> a -> b
$
            ((Int, View ViewSize stuff) -> Float)
-> [(Int, View ViewSize stuff)] -> [(Int, View ViewSize stuff)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn (ViewSize -> Float
widthFlexibility (ViewSize -> Float)
-> ((Int, View ViewSize stuff) -> ViewSize)
-> (Int, View ViewSize stuff)
-> Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. View ViewSize stuff -> ViewSize
forall ann stuff. View ann stuff -> ann
ann (View ViewSize stuff -> ViewSize)
-> ((Int, View ViewSize stuff) -> View ViewSize stuff)
-> (Int, View ViewSize stuff)
-> ViewSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, View ViewSize stuff) -> View ViewSize stuff
forall a b. (a, b) -> b
snd) ([(Int, View ViewSize stuff)] -> [(Int, View ViewSize stuff)])
-> [(Int, View ViewSize stuff)] -> [(Int, View ViewSize stuff)]
forall a b. (a -> b) -> a -> b
$ [Int] -> [View ViewSize stuff] -> [(Int, View ViewSize stuff)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0 :: Int ..] [View ViewSize stuff]
children
      numChildren :: Int
numChildren = [View ViewSize stuff] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [View ViewSize stuff]
children

      f :: (Float, Vec2)
-> (a, View ViewSize stuff)
-> ((Float, Vec2), (a, (Vec2, Box -> View Box (Placed stuff))))
f (Float
childrenRemaining, WithVec2 Float
remW Float
remH) (a
ix, View ViewSize stuff
child) =
        ( (Float
childrenRemaining Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
1.0, Float -> Float -> Vec2
vec2 (Float
remW Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
reportedWidth) Float
remH)
        , ( a
ix
          , (Vec2, Box -> View Box (Placed stuff))
child'
          ) -- XXX: can use combineH here
        )
        where
          WithVec2 Float
reportedWidth Float
_ = (Vec2, Box -> View Box (Placed stuff)) -> Vec2
forall a b. (a, b) -> a
fst (Vec2, Box -> View Box (Placed stuff))
child'
          child' :: (Vec2, Box -> View Box (Placed stuff))
child' = Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend (Float -> Float -> Vec2
vec2 Float
proposeWidth Float
remH) View ViewSize stuff
child
          proposeWidth :: Float
proposeWidth = Float
remW Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
childrenRemaining
  VStack{[View ViewSize stuff]
children :: forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View ViewSize stuff]
children} ->
    -- Like the HStack, but advancing vertically
    ( (Vec2 -> Vec2 -> Vec2) -> Vec2 -> [Vec2] -> Vec2
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Vec2 -> Vec2 -> Vec2
combineV Vec2
0 ([Vec2] -> Vec2) -> [Vec2] -> Vec2
forall a b. (a -> b) -> a -> b
$ ((Vec2, Box -> View Box (Placed stuff)) -> Vec2)
-> [(Vec2, Box -> View Box (Placed stuff))] -> [Vec2]
forall a b. (a -> b) -> [a] -> [b]
map (Vec2, Box -> View Box (Placed stuff)) -> Vec2
forall a b. (a, b) -> a
fst [(Vec2, Box -> View Box (Placed stuff))]
children'
    , \Box
placedStack ->
        let
          placedChildren :: [View Box (Placed stuff)]
          placedChildren :: [View Box (Placed stuff)]
placedChildren = (Box, [View Box (Placed stuff)]) -> [View Box (Placed stuff)]
forall a b. (a, b) -> b
snd ((Box, [View Box (Placed stuff)]) -> [View Box (Placed stuff)])
-> (Box, [View Box (Placed stuff)]) -> [View Box (Placed stuff)]
forall a b. (a -> b) -> a -> b
$ (Box
 -> (Vec2, Box -> View Box (Placed stuff))
 -> (Box, View Box (Placed stuff)))
-> Box
-> [(Vec2, Box -> View Box (Placed stuff))]
-> (Box, [View Box (Placed stuff)])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL Box
-> (Vec2, Box -> View Box (Placed stuff))
-> (Box, View Box (Placed stuff))
placeTopToBottom Box
placedStack [(Vec2, Box -> View Box (Placed stuff))]
children'
            where
              placeTopToBottom :: Box -> (Vec2, Box -> View Box (Placed stuff)) -> (Box, View Box (Placed stuff))
              placeTopToBottom :: Box
-> (Vec2, Box -> View Box (Placed stuff))
-> (Box, View Box (Placed stuff))
placeTopToBottom Box
remaining (Vec2
reportedSize, Box -> View Box (Placed stuff)
suspended) =
                ( Box
remaining'
                , Box -> View Box (Placed stuff)
suspended Box
placed
                )
                where
                  (Box
slot, Box
remaining') = Vec2 -> (Float -> Float -> (Box, Box)) -> (Box, Box)
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
reportedSize \Float
_w Float
h -> Float -> Box -> (Box, Box)
Layout.cutTop Float
h Box
remaining
                  placed :: Box
placed = Alignment -> Vec2 -> Box -> Box
Layout.placeSize Alignment
Alignment.center Vec2
reportedSize Box
slot
        in
          VStack
            { ann :: Box
ann = Box
-> (NonEmpty (View Box (Placed stuff)) -> Box)
-> Maybe (NonEmpty (View Box (Placed stuff)))
-> Box
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Box
placedStack ((View Box (Placed stuff) -> Box)
-> NonEmpty (View Box (Placed stuff)) -> Box
forall m a. Semigroup m => (a -> m) -> NonEmpty a -> m
forall (t :: * -> *) m a.
(Foldable1 t, Semigroup m) =>
(a -> m) -> t a -> m
foldMap1' View Box (Placed stuff) -> Box
forall ann stuff. View ann stuff -> ann
ann) (Maybe (NonEmpty (View Box (Placed stuff))) -> Box)
-> Maybe (NonEmpty (View Box (Placed stuff))) -> Box
forall a b. (a -> b) -> a -> b
$ [View Box (Placed stuff)]
-> Maybe (NonEmpty (View Box (Placed stuff)))
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty [View Box (Placed stuff)]
placedChildren
            , children :: [View Box (Placed stuff)]
children = [View Box (Placed stuff)]
placedChildren
            }
    )
    where
      -- | Record index, sort by flexibility, process, restore order
      children' :: [(Vec2, Box -> View Box (Placed stuff))]
children' =
        Array Int (Vec2, Box -> View Box (Placed stuff))
-> [(Vec2, Box -> View Box (Placed stuff))]
forall a. Array Int a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Array Int (Vec2, Box -> View Box (Placed stuff))
 -> [(Vec2, Box -> View Box (Placed stuff))])
-> ([(Int, (Vec2, Box -> View Box (Placed stuff)))]
    -> Array Int (Vec2, Box -> View Box (Placed stuff)))
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
-> [(Vec2, Box -> View Box (Placed stuff))]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int)
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
-> Array Int (Vec2, Box -> View Box (Placed stuff))
forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (Int
0, Int
numChildren Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) ([(Int, (Vec2, Box -> View Box (Placed stuff)))]
 -> [(Vec2, Box -> View Box (Placed stuff))])
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
-> [(Vec2, Box -> View Box (Placed stuff))]
forall a b. (a -> b) -> a -> b
$
          ((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
forall a b. (a, b) -> b
snd (((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
 -> [(Int, (Vec2, Box -> View Box (Placed stuff)))])
-> ((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
-> [(Int, (Vec2, Box -> View Box (Placed stuff)))]
forall a b. (a -> b) -> a -> b
$ ((Float, Vec2)
 -> (Int, View ViewSize stuff)
 -> ((Float, Vec2), (Int, (Vec2, Box -> View Box (Placed stuff)))))
-> (Float, Vec2)
-> [(Int, View ViewSize stuff)]
-> ((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL (Float, Vec2)
-> (Int, View ViewSize stuff)
-> ((Float, Vec2), (Int, (Vec2, Box -> View Box (Placed stuff))))
forall {stuff} {a}.
LayoutView stuff =>
(Float, Vec2)
-> (a, View ViewSize stuff)
-> ((Float, Vec2), (a, (Vec2, Box -> View Box (Placed stuff))))
f (Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
numChildren, Vec2
proposed) ([(Int, View ViewSize stuff)]
 -> ((Float, Vec2),
     [(Int, (Vec2, Box -> View Box (Placed stuff)))]))
-> [(Int, View ViewSize stuff)]
-> ((Float, Vec2), [(Int, (Vec2, Box -> View Box (Placed stuff)))])
forall a b. (a -> b) -> a -> b
$
            ((Int, View ViewSize stuff) -> Float)
-> [(Int, View ViewSize stuff)] -> [(Int, View ViewSize stuff)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn (ViewSize -> Float
heightFlexibility (ViewSize -> Float)
-> ((Int, View ViewSize stuff) -> ViewSize)
-> (Int, View ViewSize stuff)
-> Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. View ViewSize stuff -> ViewSize
forall ann stuff. View ann stuff -> ann
ann (View ViewSize stuff -> ViewSize)
-> ((Int, View ViewSize stuff) -> View ViewSize stuff)
-> (Int, View ViewSize stuff)
-> ViewSize
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, View ViewSize stuff) -> View ViewSize stuff
forall a b. (a, b) -> b
snd) ([(Int, View ViewSize stuff)] -> [(Int, View ViewSize stuff)])
-> [(Int, View ViewSize stuff)] -> [(Int, View ViewSize stuff)]
forall a b. (a -> b) -> a -> b
$ [Int] -> [View ViewSize stuff] -> [(Int, View ViewSize stuff)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0 :: Int ..] [View ViewSize stuff]
children
      numChildren :: Int
numChildren = [View ViewSize stuff] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [View ViewSize stuff]
children

      f :: (Float, Vec2)
-> (a, View ViewSize stuff)
-> ((Float, Vec2), (a, (Vec2, Box -> View Box (Placed stuff))))
f (Float
childrenRemaining, WithVec2 Float
remW Float
remH) (a
ix, View ViewSize stuff
child) =
        ( (Float
childrenRemaining Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
1.0, Float -> Float -> Vec2
vec2 Float
remW (Float
remH Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
reportedHeight))
        , ( a
ix
          , (Vec2, Box -> View Box (Placed stuff))
child'
          ) -- XXX: can use combineH here
        )
        where
          WithVec2 Float
_ Float
reportedHeight = (Vec2, Box -> View Box (Placed stuff)) -> Vec2
forall a b. (a, b) -> a
fst (Vec2, Box -> View Box (Placed stuff))
child'
          child' :: (Vec2, Box -> View Box (Placed stuff))
child' = Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend (Float -> Float -> Vec2
vec2 Float
remW Float
proposeHeight) View ViewSize stuff
child
          proposeHeight :: Float
proposeHeight = Float
remH Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
childrenRemaining
  ZStack{[View ViewSize stuff]
children :: forall ann stuff. View ann stuff -> [View ann stuff]
children :: [View ViewSize stuff]
children} ->
    ( (Vec2 -> Vec2 -> Vec2) -> Vec2 -> [Vec2] -> Vec2
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Vec2 -> Vec2 -> Vec2
max2 Vec2
0 [Vec2]
reporteds
    , \Box
placedStack ->
        let
          placedChildren :: [View Box (Placed stuff)]
placedChildren = ((Box -> View Box (Placed stuff)) -> View Box (Placed stuff))
-> [Box -> View Box (Placed stuff)] -> [View Box (Placed stuff)]
forall a b. (a -> b) -> [a] -> [b]
map ((Box -> View Box (Placed stuff)) -> Box -> View Box (Placed stuff)
forall a b. (a -> b) -> a -> b
$ Box
placedStack) [Box -> View Box (Placed stuff)]
suspendeds
        in
          ZStack
            { ann :: Box
ann = Box
-> (NonEmpty (View Box (Placed stuff)) -> Box)
-> Maybe (NonEmpty (View Box (Placed stuff)))
-> Box
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Box
placedStack ((View Box (Placed stuff) -> Box)
-> NonEmpty (View Box (Placed stuff)) -> Box
forall m a. Semigroup m => (a -> m) -> NonEmpty a -> m
forall (t :: * -> *) m a.
(Foldable1 t, Semigroup m) =>
(a -> m) -> t a -> m
foldMap1' View Box (Placed stuff) -> Box
forall ann stuff. View ann stuff -> ann
ann) (Maybe (NonEmpty (View Box (Placed stuff))) -> Box)
-> Maybe (NonEmpty (View Box (Placed stuff))) -> Box
forall a b. (a -> b) -> a -> b
$ [View Box (Placed stuff)]
-> Maybe (NonEmpty (View Box (Placed stuff)))
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty [View Box (Placed stuff)]
placedChildren
            , children :: [View Box (Placed stuff)]
children = [View Box (Placed stuff)]
placedChildren
            }
    )
    where
      ([Vec2]
reporteds, [Box -> View Box (Placed stuff)]
suspendeds) = [(Vec2, Box -> View Box (Placed stuff))]
-> ([Vec2], [Box -> View Box (Placed stuff)])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(Vec2, Box -> View Box (Placed stuff))]
 -> ([Vec2], [Box -> View Box (Placed stuff)]))
-> [(Vec2, Box -> View Box (Placed stuff))]
-> ([Vec2], [Box -> View Box (Placed stuff)])
forall a b. (a -> b) -> a -> b
$ (View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff)))
-> [View ViewSize stuff]
-> [(Vec2, Box -> View Box (Placed stuff))]
forall a b. (a -> b) -> [a] -> [b]
map (Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend Vec2
proposed) [View ViewSize stuff]
children
  Overlay{View ViewSize stuff
primary :: forall ann stuff. View ann stuff -> View ann stuff
primary :: View ViewSize stuff
primary, View ViewSize stuff
secondary :: forall ann stuff. View ann stuff -> View ann stuff
secondary :: View ViewSize stuff
secondary} ->
    ( Vec2
reportedPri
    , \Box
placed ->
        let
          placedPrimary :: View Box (Placed stuff)
placedPrimary = Box -> View Box (Placed stuff)
suspendedPri Box
placed
        in
          Overlay
            { ann :: Box
ann = Box
placed
            , primary :: View Box (Placed stuff)
primary = View Box (Placed stuff)
placedPrimary
            , secondary :: View Box (Placed stuff)
secondary = Box -> View Box (Placed stuff)
suspendedSec View Box (Placed stuff)
placedPrimary.ann -- inspect primary box
            }
    )
    where
      (Vec2
reportedPri, Box -> View Box (Placed stuff)
suspendedPri) = Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend Vec2
proposed View ViewSize stuff
primary
      (Vec2
_reportedSec, Box -> View Box (Placed stuff)
suspendedSec) = Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
forall stuff.
LayoutView stuff =>
Vec2
-> View ViewSize stuff -> (Vec2, Box -> View Box (Placed stuff))
suspend Vec2
reportedPri View ViewSize stuff
secondary -- inspect primary size

-- * Internals

inf :: Float
inf :: Float
inf = Float
1 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
0

widthFlexibility :: ViewSize -> Float
widthFlexibility :: ViewSize -> Float
widthFlexibility ViewSize{Maybe Float
minWidth :: ViewSize -> Maybe Float
maxWidth :: ViewSize -> Maybe Float
minHeight :: ViewSize -> Maybe Float
maxHeight :: ViewSize -> Maybe Float
minWidth :: Maybe Float
maxWidth :: Maybe Float
minHeight :: Maybe Float
maxHeight :: Maybe Float
..} = Float
-> (Float -> Float -> Float) -> Maybe Float -> Maybe Float -> Float
forall t1 t2 t3.
t1 -> (t2 -> t3 -> t1) -> Maybe t2 -> Maybe t3 -> t1
maybeBoth (-Float
1) (-) Maybe Float
maxWidth Maybe Float
minWidth

heightFlexibility :: ViewSize -> Float
heightFlexibility :: ViewSize -> Float
heightFlexibility ViewSize{Maybe Float
minWidth :: ViewSize -> Maybe Float
maxWidth :: ViewSize -> Maybe Float
minHeight :: ViewSize -> Maybe Float
maxHeight :: ViewSize -> Maybe Float
minWidth :: Maybe Float
maxWidth :: Maybe Float
minHeight :: Maybe Float
maxHeight :: Maybe Float
..} = Float
-> (Float -> Float -> Float) -> Maybe Float -> Maybe Float -> Float
forall t1 t2 t3.
t1 -> (t2 -> t3 -> t1) -> Maybe t2 -> Maybe t3 -> t1
maybeBoth (-Float
1) (-) Maybe Float
maxHeight Maybe Float
minHeight

vsClamp :: Vec2 -> ViewSize -> Vec2 -> Vec2
vsClamp :: Vec2 -> ViewSize -> Vec2 -> Vec2
vsClamp Vec2
parent ViewSize{Maybe Float
minWidth :: ViewSize -> Maybe Float
maxWidth :: ViewSize -> Maybe Float
minHeight :: ViewSize -> Maybe Float
maxHeight :: ViewSize -> Maybe Float
minWidth :: Maybe Float
maxWidth :: Maybe Float
minHeight :: Maybe Float
maxHeight :: Maybe Float
..} Vec2
v =
  Vec2 -> (Float -> Float -> Vec2) -> Vec2
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
parent \Float
pw Float
ph ->
    Vec2 -> (Float -> Float -> Vec2) -> Vec2
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
v \Float
w Float
h ->
      Float -> Float -> Vec2
vec2
        (Float
-> (Float -> Float -> Float) -> Maybe Float -> Maybe Float -> Float
forall t1 t2 t3.
t1 -> (t2 -> t3 -> t1) -> Maybe t2 -> Maybe t3 -> t1
maybeBoth Float
pw (Float -> Float -> Float -> Float
forall edge a. GlClamp edge a => a -> edge -> edge -> a
glClamp Float
w) Maybe Float
minWidth Maybe Float
maxWidth)
        (Float
-> (Float -> Float -> Float) -> Maybe Float -> Maybe Float -> Float
forall t1 t2 t3.
t1 -> (t2 -> t3 -> t1) -> Maybe t2 -> Maybe t3 -> t1
maybeBoth Float
ph (Float -> Float -> Float -> Float
forall edge a. GlClamp edge a => a -> edge -> edge -> a
glClamp Float
h) Maybe Float
minHeight Maybe Float
maxHeight)

{-# INLINE maybeBoth #-}
maybeBoth :: t1 -> (t2 -> t3 -> t1) -> Maybe t2 -> Maybe t3 -> t1
maybeBoth :: forall t1 t2 t3.
t1 -> (t2 -> t3 -> t1) -> Maybe t2 -> Maybe t3 -> t1
maybeBoth t1
_ t2 -> t3 -> t1
j (Just t2
a) (Just t3
b) = t2 -> t3 -> t1
j t2
a t3
b
maybeBoth t1
n t2 -> t3 -> t1
_ Maybe t2
_ Maybe t3
_ = t1
n

combineH :: Vec2 -> Vec2 -> Vec2
combineH :: Vec2 -> Vec2 -> Vec2
combineH Vec2
a Vec2
b =
  Vec2 -> (Float -> Float -> Vec2) -> Vec2
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
a \Float
aw Float
ah ->
    Vec2 -> (Float -> Float -> Vec2) -> Vec2
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
b \Float
bw Float
bh ->
      Float -> Float -> Vec2
vec2 (Float
aw Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
bw) (Float -> Float -> Float
forall a. Ord a => a -> a -> a
max Float
ah Float
bh)

combineV :: Vec2 -> Vec2 -> Vec2
combineV :: Vec2 -> Vec2 -> Vec2
combineV Vec2
a Vec2
b =
  Vec2 -> (Float -> Float -> Vec2) -> Vec2
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
a \Float
aw Float
ah ->
    Vec2 -> (Float -> Float -> Vec2) -> Vec2
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
b \Float
bw Float
bh ->
      Float -> Float -> Vec2
vec2 (Float -> Float -> Float
forall a. Ord a => a -> a -> a
max Float
aw Float
bw) (Float
ah Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
bh)

max2 :: Vec2 -> Vec2 -> Vec2
max2 :: Vec2 -> Vec2 -> Vec2
max2 Vec2
a Vec2
b =
  Vec2 -> (Float -> Float -> Vec2) -> Vec2
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
a \Float
aw Float
ah ->
    Vec2 -> (Float -> Float -> Vec2) -> Vec2
forall r. Vec2 -> (Float -> Float -> r) -> r
withVec2 Vec2
b \Float
bw Float
bh ->
      Float -> Float -> Vec2
vec2 (Float -> Float -> Float
forall a. Ord a => a -> a -> a
max Float
aw Float
bw) (Float -> Float -> Float
forall a. Ord a => a -> a -> a
max Float
ah Float
bh)