{-# LANGUAGE DeriveDataTypeable    #-}
{-# LANGUAGE ViewPatterns          #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards       #-}
{-# LANGUAGE TupleSections         #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE UndecidableInstances  #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Plots.Types.Bar
-- Copyright   :  (C) 2015 Christopher Chalmers
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Christopher Chalmers
-- Stability   :  experimental
-- Portability :  non-portable
--
-- A bar plot is a plot that presents data with rectangular bars with
-- lengths proportional to the values that they represent. The bars can
-- be plotted vertically or horizontally.
--
-- <<diagrams/src_Plots_Types_Bar_multiBarExample.svg#diagram=multiBarExample&height=350>>
--
-- (see 'multiBars' example for code to make this plot)
--
----------------------------------------------------------------------------
module Plots.Types.Bar
  (
    -- * BarPlot
    BarPlot
  , barPlot
  , barPlot'
  , namedBarPlot
  , namedBarPlot'
  , floatingBarPlot

    -- * Bar layout
  , BarLayout
  , HasBarLayout (..)

    -- * Multi bars
    -- ** Adding to axis
  , multiBars
  , MultiBarState

    -- ** Multi bar types
  , groupedBars
  , groupedBars'
  , stackedBars
  , stackedEqualBars
  , runningBars

    -- ** Modify multi bars
  , onBars
  , labelBars


    -- * Low level constructors
  , mkBars
  , mkFloatingBars
  , mkRunningBars
  , mkStackedBars
  , mkStackedEqualBars
  , mkGroupedBars
  -- , barAxisLabels

  ) where

import           Control.Lens            hiding (at, none, transform, ( # ))
import           Control.Monad.State
import           Data.Typeable
import qualified Data.Foldable as F

import           Plots.Style
import           Plots.Types
import           Plots.Axis
import           Plots.Axis.Ticks
import           Plots.Axis.Labels
import           Plots.Util

import qualified Data.List               as List
import           Diagrams.Core.Transform (fromSymmetric)
import           Linear.V2               (_yx)

import           Diagrams.Prelude

-- Single bar ----------------------------------------------------------

-- | Data for a single bar. The bar is drawn as
--
-- @
-- fromCorners (V2 barPos (fst barBounds))) (V2 (barPos + barWidth) (snd barBounds))
-- @
--
--   for 'Horizontal' bars, flipped for 'Vertical'. This is a low level
--   representation of a bar and is not intended to be used directly.

-- | Construct a rectangle of size v with the bottom centre at point p.
rectB :: (InSpace V2 n t, TrailLike t) => Point V2 n -> V2 n -> t
rectB :: forall n t.
(InSpace V2 n t, TrailLike t) =>
Point V2 n -> V2 n -> t
rectB Point V2 n
p (V2 n
x n
y) =
  Located (Trail (V t) (N t)) -> t
forall t. TrailLike t => Located (Trail (V t) (N t)) -> t
trailLike (Located (Trail (V t) (N t)) -> t)
-> Located (Trail (V t) (N t)) -> t
forall a b. (a -> b) -> a -> b
$ [Vn (Trail V2 n)] -> Trail V2 n
forall t. TrailLike t => [Vn t] -> t
fromOffsets [n -> n -> V2 n
forall a. a -> a -> V2 a
V2 n
x n
0, n -> n -> V2 n
forall a. a -> a -> V2 a
V2 n
0 n
y, n -> n -> V2 n
forall a. a -> a -> V2 a
V2 (-n
x) n
0] Trail V2 n -> (Trail V2 n -> Trail V2 n) -> Trail V2 n
forall a b. a -> (a -> b) -> b
# Trail V2 n -> Trail V2 n
forall (v :: * -> *) n. Trail v n -> Trail v n
closeTrail Trail V2 n
-> Point (V (Trail V2 n)) (N (Trail V2 n)) -> Located (Trail V2 n)
forall a. a -> Point (V a) (N a) -> Located a
`at` Point V2 n
p Point V2 n -> Diff (Point V2) n -> Point V2 n
forall (p :: * -> *) a. (Affine p, Num a) => p a -> Diff p a -> p a
.-^ n -> n -> V2 n
forall a. a -> a -> V2 a
V2 (n
xn -> n -> n
forall a. Fractional a => a -> a -> a
/n
2) n
0

------------------------------------------------------------------------
-- Bar layout
------------------------------------------------------------------------

-- | The way an individual bar plot or a group of bars plots are laid
--   out on the axis.
data BarLayout n = BarLayout
  { forall n. BarLayout n -> Orientation
bOrient  :: Orientation
  , forall n. BarLayout n -> n
bWidth   :: n
  , forall n. BarLayout n -> n
bSpacing :: n
  , forall n. BarLayout n -> n
bStart   :: n
  } deriving Typeable

instance Fractional n => Default (BarLayout n) where
  def :: BarLayout n
def = Orientation -> n -> n -> n -> BarLayout n
forall n. Orientation -> n -> n -> n -> BarLayout n
BarLayout Orientation
Horizontal n
0.8 n
1 n
1

type instance N (BarLayout n) = n

instance HasOrientation (BarLayout n) where
  orientation :: Lens' (BarLayout n) Orientation
orientation = (BarLayout n -> Orientation)
-> (BarLayout n -> Orientation -> BarLayout n)
-> Lens' (BarLayout n) Orientation
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens BarLayout n -> Orientation
forall n. BarLayout n -> Orientation
bOrient (\BarLayout n
bl Orientation
o -> BarLayout n
bl {bOrient :: Orientation
bOrient = Orientation
o})

-- | Class of things that have a modifiable 'BarLayout'.
class HasOrientation a => HasBarLayout a where
  -- | Lens onto the 'BarLayout'
  barLayout :: Lens' a (BarLayout (N a))

  -- | The width bar for single / stacked bars or the width of a group
  --   for grouped bar plot.
  --
  --   Default is @0.8@
  barWidth :: Lens' a (N a)
  barWidth = (BarLayout (N a) -> f (BarLayout (N a))) -> a -> f a
forall a. HasBarLayout a => Lens' a (BarLayout (N a))
barLayout ((BarLayout (N a) -> f (BarLayout (N a))) -> a -> f a)
-> ((N a -> f (N a)) -> BarLayout (N a) -> f (BarLayout (N a)))
-> (N a -> f (N a))
-> a
-> f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (BarLayout (N a) -> N a)
-> (BarLayout (N a) -> N a -> BarLayout (N a))
-> Lens (BarLayout (N a)) (BarLayout (N a)) (N a) (N a)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens BarLayout (N a) -> N a
forall n. BarLayout n -> n
bWidth (\BarLayout (N a)
bl N a
w -> BarLayout (N a)
bl {bWidth :: N a
bWidth = N a
w})

  -- | The spacing between each bar or group of bars.
  --
  --   Default is @1@
  barSpacing :: Lens' a (N a)
  barSpacing = (BarLayout (N a) -> f (BarLayout (N a))) -> a -> f a
forall a. HasBarLayout a => Lens' a (BarLayout (N a))
barLayout ((BarLayout (N a) -> f (BarLayout (N a))) -> a -> f a)
-> ((N a -> f (N a)) -> BarLayout (N a) -> f (BarLayout (N a)))
-> (N a -> f (N a))
-> a
-> f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (BarLayout (N a) -> N a)
-> (BarLayout (N a) -> N a -> BarLayout (N a))
-> Lens (BarLayout (N a)) (BarLayout (N a)) (N a) (N a)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens BarLayout (N a) -> N a
forall n. BarLayout n -> n
bSpacing (\BarLayout (N a)
bl N a
s -> BarLayout (N a)
bl {bSpacing :: N a
bSpacing = N a
s})

  -- | The distance from the axis to centre of the first bar.
  --
  --   Default is @1@
  barStart :: Lens' a (N a)
  barStart = (BarLayout (N a) -> f (BarLayout (N a))) -> a -> f a
forall a. HasBarLayout a => Lens' a (BarLayout (N a))
barLayout ((BarLayout (N a) -> f (BarLayout (N a))) -> a -> f a)
-> ((N a -> f (N a)) -> BarLayout (N a) -> f (BarLayout (N a)))
-> (N a -> f (N a))
-> a
-> f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (BarLayout (N a) -> N a)
-> (BarLayout (N a) -> N a -> BarLayout (N a))
-> Lens (BarLayout (N a)) (BarLayout (N a)) (N a) (N a)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens BarLayout (N a) -> N a
forall n. BarLayout n -> n
bStart (\BarLayout (N a)
bl N a
x -> BarLayout (N a)
bl {bStart :: N a
bStart = N a
x})

instance HasBarLayout (BarLayout n) where
  barLayout :: Lens' (BarLayout n) (BarLayout (N (BarLayout n)))
barLayout = (BarLayout (N (BarLayout n)) -> f (BarLayout (N (BarLayout n))))
-> BarLayout n -> f (BarLayout n)
forall a. a -> a
id

instance HasBarLayout a => HasBarLayout (Plot a b) where
  barLayout :: Lens' (Plot a b) (BarLayout (N (Plot a b)))
barLayout = (a -> f a) -> Plot a b -> f (Plot a b)
forall p p' b. SameSpace p p' => Lens (Plot p b) (Plot p' b) p p'
rawPlot ((a -> f a) -> Plot a b -> f (Plot a b))
-> ((BarLayout (N a) -> f (BarLayout (N a))) -> a -> f a)
-> (BarLayout (N a) -> f (BarLayout (N a)))
-> Plot a b
-> f (Plot a b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (BarLayout (N a) -> f (BarLayout (N a))) -> a -> f a
forall a. HasBarLayout a => Lens' a (BarLayout (N a))
barLayout

------------------------------------------------------------------------
-- Bar plot type
------------------------------------------------------------------------

-- | A bar plot for a single set of bars. Multi-bar plots are achieved
--   by having multiple 'BarPlot's. Each bar plot corresponds to a
--   single legend entry. To get multiple bar entries/colours, use
--   multiple 'BarPlots'

--   A 'BarPlot' is not intended to be constructed directly, instead use
--   one of the helper functions.
data BarPlot n = BarPlot
  { forall n. BarPlot n -> [(n, n)]
bpData   :: [(n,n)]
  , forall n. BarPlot n -> BarLayout n
bpLayout :: BarLayout n
  } deriving Typeable

type instance V (BarPlot n) = V2
type instance N (BarPlot n) = n

instance HasOrientation (BarPlot n) where
  orientation :: Lens' (BarPlot n) Orientation
orientation = (BarLayout n -> f (BarLayout n)) -> BarPlot n -> f (BarPlot n)
forall a. HasBarLayout a => Lens' a (BarLayout (N a))
barLayout ((BarLayout n -> f (BarLayout n)) -> BarPlot n -> f (BarPlot n))
-> ((Orientation -> f Orientation)
    -> BarLayout n -> f (BarLayout n))
-> (Orientation -> f Orientation)
-> BarPlot n
-> f (BarPlot n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Orientation -> f Orientation) -> BarLayout n -> f (BarLayout n)
forall a. HasOrientation a => Lens' a Orientation
orientation

instance OrderedField n => Enveloped (BarPlot n) where
  getEnvelope :: BarPlot n -> Envelope (V (BarPlot n)) (N (BarPlot n))
getEnvelope BarPlot {[(n, n)]
BarLayout n
bpLayout :: BarLayout n
bpData :: [(n, n)]
bpLayout :: forall n. BarPlot n -> BarLayout n
bpData :: forall n. BarPlot n -> [(n, n)]
..} =
    Path V2 n -> Envelope (V (BarPlot n)) (N (BarPlot n))
forall a. Enveloped a => a -> Envelope (V a) (N a)
getEnvelope (Path V2 n -> Envelope (V (BarPlot n)) (N (BarPlot n)))
-> (Path V2 n -> Path V2 n)
-> Path V2 n
-> Envelope (V (BarPlot n)) (N (BarPlot n))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BarLayout n
-> (Path V2 n -> Path V2 n)
-> (Path V2 n -> Path V2 n)
-> Path V2 n
-> Path V2 n
forall o a. HasOrientation o => o -> a -> a -> a
orient BarLayout n
bpLayout Path V2 n -> Path V2 n
forall (v :: * -> *) n t.
(InSpace v n t, R2 v, Transformable t) =>
t -> t
_reflectXY Path V2 n -> Path V2 n
forall a. a -> a
id (Path V2 n -> Path V2 n)
-> (Path V2 n -> Path V2 n) -> Path V2 n -> Path V2 n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. a -> a
forall {v :: * -> *} {n}. Path v n -> Path v n
id :: Path v n -> Path v n) (Path V2 n -> Envelope (V (BarPlot n)) (N (BarPlot n)))
-> Path V2 n -> Envelope (V (BarPlot n)) (N (BarPlot n))
forall a b. (a -> b) -> a -> b
$
      (Int -> (n, n) -> Path V2 n) -> [(n, n)] -> Path V2 n
forall i (f :: * -> *) m a.
(FoldableWithIndex i f, Monoid m) =>
(i -> a -> m) -> f a -> m
ifoldMap Int -> (n, n) -> Path V2 n
drawBar [(n, n)]
bpData
    where
      drawBar :: Int -> (n, n) -> Path V2 n
drawBar Int
i (n
a,n
b) = Point V2 n -> V2 n -> Path V2 n
forall n t.
(InSpace V2 n t, TrailLike t) =>
Point V2 n -> V2 n -> t
rectB (n -> n -> Point V2 n
forall n. n -> n -> P2 n
mkP2 n
x n
a) (n -> n -> V2 n
forall a. a -> a -> V2 a
V2 (Getting n (BarLayout n) n -> BarLayout n -> n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting n (BarLayout n) n
forall a. HasBarLayout a => Lens' a (N a)
barWidth BarLayout n
bpLayout) (n
b n -> n -> n
forall a. Num a => a -> a -> a
- n
a))
        where x :: n
x = Getting n (BarLayout n) n -> BarLayout n -> n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting n (BarLayout n) n
forall a. HasBarLayout a => Lens' a (N a)
barStart BarLayout n
bpLayout n -> n -> n
forall a. Num a => a -> a -> a
+ Int -> n
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i n -> n -> n
forall a. Num a => a -> a -> a
* Getting n (BarLayout n) n -> BarLayout n -> n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting n (BarLayout n) n
forall a. HasBarLayout a => Lens' a (N a)
barSpacing BarLayout n
bpLayout

instance (TypeableFloat n, Renderable (Path V2 n) b)
    => Plotable (BarPlot n) b where
  renderPlotable :: forall (v :: * -> *) n.
InSpace v n (BarPlot n) =>
AxisSpec v n -> PlotStyle b v n -> BarPlot n -> QDiagram b v n Any
renderPlotable AxisSpec v n
s PlotStyle b v n
sty BarPlot {[(n, n)]
BarLayout n
bpLayout :: BarLayout n
bpData :: [(n, n)]
bpLayout :: forall n. BarPlot n -> BarLayout n
bpData :: forall n. BarPlot n -> [(n, n)]
..} =
    (Int -> (n, n) -> QDiagram b v n Any)
-> [(n, n)] -> QDiagram b v n Any
forall i (f :: * -> *) m a.
(FoldableWithIndex i f, Monoid m) =>
(i -> a -> m) -> f a -> m
ifoldMap Int -> (n, n) -> QDiagram b v n Any
drawBar [(n, n)]
bpData
      # orient bpLayout _reflectXY id
      # applyAreaStyle sty
      # transform (s^.specTrans)
    where
      drawBar :: Int -> (n, n) -> QDiagram b v n Any
drawBar Int
i (n
a,n
b) = Point V2 n -> V2 n -> QDiagram b v n Any
forall n t.
(InSpace V2 n t, TrailLike t) =>
Point V2 n -> V2 n -> t
rectB (n -> n -> Point V2 n
forall n. n -> n -> P2 n
mkP2 n
x n
a) (n -> n -> V2 n
forall a. a -> a -> V2 a
V2 (Getting n (BarLayout n) n -> BarLayout n -> n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting n (BarLayout n) n
forall a. HasBarLayout a => Lens' a (N a)
barWidth BarLayout n
bpLayout) (n
b n -> n -> n
forall a. Num a => a -> a -> a
- n
a))
        where x :: n
x = Getting n (BarLayout n) n -> BarLayout n -> n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting n (BarLayout n) n
forall a. HasBarLayout a => Lens' a (N a)
barStart BarLayout n
bpLayout n -> n -> n
forall a. Num a => a -> a -> a
+ Int -> n
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i n -> n -> n
forall a. Num a => a -> a -> a
* Getting n (BarLayout n) n -> BarLayout n -> n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting n (BarLayout n) n
forall a. HasBarLayout a => Lens' a (N a)
barSpacing BarLayout n
bpLayout

  defLegendPic :: forall (v :: * -> *) n.
InSpace v n (BarPlot n) =>
PlotStyle b v n -> BarPlot n -> QDiagram b v n Any
defLegendPic PlotStyle b v n
sty BarPlot {[(n, n)]
BarLayout n
bpLayout :: BarLayout n
bpData :: [(n, n)]
bpLayout :: forall n. BarPlot n -> BarLayout n
bpData :: forall n. BarPlot n -> [(n, n)]
..}
    = QDiagram b v n Any -> QDiagram b v n Any
forall (v :: * -> *) n a.
(InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a) =>
a -> a
centerXY
    (QDiagram b v n Any -> QDiagram b v n Any)
-> (QDiagram b v n Any -> QDiagram b v n Any)
-> QDiagram b v n Any
-> QDiagram b v n Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PlotStyle b v n -> QDiagram b v n Any -> QDiagram b v n Any
forall a t b.
(SameSpace a t, HasPlotStyle (Const (PlotStyle b (V a) (N a))) a b,
 HasStyle t) =>
a -> t -> t
applyAreaStyle PlotStyle b v n
sty'
    (QDiagram b v n Any -> QDiagram b v n Any)
-> (QDiagram b v n Any -> QDiagram b v n Any)
-> QDiagram b v n Any
-> QDiagram b v n Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BarLayout n
-> (QDiagram b v n Any -> QDiagram b v n Any)
-> (QDiagram b v n Any -> QDiagram b v n Any)
-> QDiagram b v n Any
-> QDiagram b v n Any
forall o a. HasOrientation o => o -> a -> a -> a
orient BarLayout n
bpLayout QDiagram b v n Any -> QDiagram b v n Any
forall (v :: * -> *) n t.
(InSpace v n t, R2 v, Transformable t) =>
t -> t
_reflectXY QDiagram b v n Any -> QDiagram b v n Any
forall a. a -> a
id
    (QDiagram b v n Any -> QDiagram b v n Any)
-> QDiagram b v n Any -> QDiagram b v n Any
forall a b. (a -> b) -> a -> b
$ QDiagram b v n Any
d
    where
      -- Multiple bars get two bars next to each other for the legend. A
      -- single bar only gets one bar in the legend.
      d :: QDiagram b v n Any
d | Getting Any [(n, n)] (n, n) -> [(n, n)] -> Bool
forall s a. Getting Any s a -> s -> Bool
has (Index [(n, n)] -> Traversal' [(n, n)] (IxValue [(n, n)])
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Int
Index [(n, n)]
1) [(n, n)]
bpData = QDiagram b v n Any -> QDiagram b v n Any
forall n a.
(InSpace V2 n a, Fractional n, Alignable a, HasOrigin a) =>
a -> a
alignB (n -> n -> QDiagram b v n Any
forall n t. (InSpace V2 n t, TrailLike t) => n -> n -> t
rect n
4 n
7) QDiagram b v n Any -> QDiagram b v n Any -> QDiagram b v n Any
forall n a.
(InSpace V2 n a, Juxtaposable a, Semigroup a) =>
a -> a -> a
||| n -> QDiagram b v n Any
forall (v :: * -> *) n b m.
(Metric v, R1 v, OrderedField n) =>
n -> QDiagram b v n m
strutX n
3 QDiagram b v n Any -> QDiagram b v n Any -> QDiagram b v n Any
forall n a.
(InSpace V2 n a, Juxtaposable a, Semigroup a) =>
a -> a -> a
||| QDiagram b v n Any -> QDiagram b v n Any
forall n a.
(InSpace V2 n a, Fractional n, Alignable a, HasOrigin a) =>
a -> a
alignB (n -> n -> QDiagram b v n Any
forall n t. (InSpace V2 n t, TrailLike t) => n -> n -> t
rect n
4 n
10)
        | Bool
otherwise         = n -> n -> QDiagram b v n Any
forall n t. (InSpace V2 n t, TrailLike t) => n -> n -> t
rect n
4 n
10

      -- The legend bars don't look right if the line width is too big so we limit it
      sty' :: PlotStyle b v n
sty' = PlotStyle b v n
sty PlotStyle b v n
-> (PlotStyle b v n -> PlotStyle b v n) -> PlotStyle b v n
forall a b. a -> (a -> b) -> b
& (Style V2 n -> Identity (Style V2 n))
-> PlotStyle b v n -> Identity (PlotStyle b v n)
forall (f :: * -> *) a b.
(HasPlotStyle f a b, Settable f) =>
LensLike' f a (Style (V a) (N a))
areaStyle ((Style V2 n -> Identity (Style V2 n))
 -> PlotStyle b v n -> Identity (PlotStyle b v n))
-> ((Measure n -> Identity (Measure n))
    -> Style V2 n -> Identity (Style V2 n))
-> (Measure n -> Identity (Measure n))
-> PlotStyle b v n
-> Identity (PlotStyle b v n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Measure n -> Identity (Measure n))
-> Style V2 n -> Identity (Style V2 n)
forall n (v :: * -> *).
(Typeable n, OrderedField n) =>
Lens' (Style v n) (Measure n)
_lw ((Measure n -> Identity (Measure n))
 -> PlotStyle b v n -> Identity (PlotStyle b v n))
-> (Measure n -> Measure n) -> PlotStyle b v n -> PlotStyle b v n
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Measure n -> Measure n -> Measure n
forall n. Ord n => Measure n -> Measure n -> Measure n
atMost (n -> Measure n
forall n. Num n => n -> Measure n
local n
0.8)

instance HasBarLayout (BarPlot n) where
  barLayout :: Lens' (BarPlot n) (BarLayout (N (BarPlot n)))
barLayout = (BarPlot n -> BarLayout n)
-> (BarPlot n -> BarLayout n -> BarPlot n)
-> Lens (BarPlot n) (BarPlot n) (BarLayout n) (BarLayout n)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens BarPlot n -> BarLayout n
forall n. BarPlot n -> BarLayout n
bpLayout (\BarPlot n
bp BarLayout n
l -> BarPlot n
bp {bpLayout :: BarLayout n
bpLayout = BarLayout n
l})

------------------------------------------------------------------------
-- Constructing bar plots
------------------------------------------------------------------------

-- | Create equidistant bars using the values.
mkBars :: (F.Foldable f, Num n) => BarLayout n -> f n -> BarPlot n
mkBars :: forall (f :: * -> *) n.
(Foldable f, Num n) =>
BarLayout n -> f n -> BarPlot n
mkBars BarLayout n
bl (f n -> [n]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList -> [n]
ns) = BarLayout n -> [(n, n)] -> BarPlot n
forall (f :: * -> *) n.
Foldable f =>
BarLayout n -> f (n, n) -> BarPlot n
mkFloatingBars BarLayout n
bl ((n -> (n, n)) -> [n] -> [(n, n)]
forall a b. (a -> b) -> [a] -> [b]
map (n
0,) [n]
ns)

-- | Create equidistant bars with lower and upper bounds for each bar.
mkFloatingBars :: F.Foldable f => BarLayout n -> f (n,n) -> BarPlot n
mkFloatingBars :: forall (f :: * -> *) n.
Foldable f =>
BarLayout n -> f (n, n) -> BarPlot n
mkFloatingBars BarLayout n
bl (f (n, n) -> [(n, n)]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList -> [(n, n)]
ns) = BarPlot
  { bpData :: [(n, n)]
bpData   = [(n, n)]
ns
  , bpLayout :: BarLayout n
bpLayout = BarLayout n
bl
  }

-- | Create uniform bars from groups of data, placing one group after
--   the other.
mkRunningBars
  :: Num n
  => BarLayout n
  -> [[(n,n)]]
  -> [BarPlot n]
mkRunningBars :: forall n. Num n => BarLayout n -> [[(n, n)]] -> [BarPlot n]
mkRunningBars BarLayout n
bl = (n, [BarPlot n]) -> [BarPlot n]
forall a b. (a, b) -> b
snd ((n, [BarPlot n]) -> [BarPlot n])
-> ([[(n, n)]] -> (n, [BarPlot n])) -> [[(n, n)]] -> [BarPlot n]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([(n, n)] -> (n, [BarPlot n]) -> (n, [BarPlot n]))
-> (n, [BarPlot n]) -> [[(n, n)]] -> (n, [BarPlot n])
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr [(n, n)] -> (n, [BarPlot n]) -> (n, [BarPlot n])
f (Getting n (BarLayout n) n -> BarLayout n -> n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting n (BarLayout n) n
forall a. HasBarLayout a => Lens' a (N a)
barStart BarLayout n
bl, [])
  where
    f :: [(n, n)] -> (n, [BarPlot n]) -> (n, [BarPlot n])
f [(n, n)]
d (n
x, [BarPlot n]
bs) = (n
x n -> n -> n
forall a. Num a => a -> a -> a
+ n
dx, BarLayout n -> [(n, n)] -> BarPlot n
forall (f :: * -> *) n.
Foldable f =>
BarLayout n -> f (n, n) -> BarPlot n
mkFloatingBars BarLayout n
bl {bStart :: n
bStart = n
x} [(n, n)]
d BarPlot n -> [BarPlot n] -> [BarPlot n]
forall a. a -> [a] -> [a]
: [BarPlot n]
bs)
      where dx :: n
dx = Getting n (BarLayout n) n -> BarLayout n -> n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting n (BarLayout n) n
forall a. HasBarLayout a => Lens' a (N a)
barSpacing BarLayout n
bl n -> n -> n
forall a. Num a => a -> a -> a
* Int -> n
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([(n, n)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(n, n)]
d)

-- | Create uniform bars from groups of data, placing one on top of the
--   other. The first list will be the same as @mkUniformBars opts (map
--   (0,) ys)@, subsequent lists will be placed on top.
mkStackedBars
  :: Num n
  => BarLayout n
  -> [[n]] -- values
  -> [BarPlot n]
mkStackedBars :: forall n. Num n => BarLayout n -> [[n]] -> [BarPlot n]
mkStackedBars BarLayout n
bl = ([n], [BarPlot n]) -> [BarPlot n]
forall a b. (a, b) -> b
snd (([n], [BarPlot n]) -> [BarPlot n])
-> ([[n]] -> ([n], [BarPlot n])) -> [[n]] -> [BarPlot n]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([n] -> [n] -> ([n], BarPlot n))
-> [n] -> [[n]] -> ([n], [BarPlot n])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
List.mapAccumR [n] -> [n] -> ([n], BarPlot n)
f (n -> [n]
forall a. a -> [a]
repeat n
0)
  where
    -- y0s are the base values for this set of bars, these accumulate
    -- for each set of data
    f :: [n] -> [n] -> ([n], BarPlot n)
f [n]
y0s [n]
ys = ([n]
y1s, BarLayout n -> [(n, n)] -> BarPlot n
forall (f :: * -> *) n.
Foldable f =>
BarLayout n -> f (n, n) -> BarPlot n
mkFloatingBars BarLayout n
bl [(n, n)]
ds)
      where y1s :: [n]
y1s  = (n -> n -> n) -> [n] -> [n] -> [n]
forall (f :: * -> *) a.
Additive f =>
(a -> a -> a) -> f a -> f a -> f a
liftU2 n -> n -> n
forall a. Num a => a -> a -> a
(+) [n]
y0s [n]
ys
            ds :: [(n, n)]
ds   = (n -> n -> (n, n)) -> [n] -> [n] -> [(n, n)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\n
y0 n
y -> (n
y0, n
y0 n -> n -> n
forall a. Num a => a -> a -> a
+ n
y)) [n]
y0s [n]
ys

-- | Similar to 'mkMultiStacked' but stack has the same height.
mkStackedEqualBars
  :: Fractional n
  => n     -- ^ value each bar reaches
  -> BarLayout n
  -> [[n]] -- ^ values
  -> [BarPlot n]
mkStackedEqualBars :: forall n. Fractional n => n -> BarLayout n -> [[n]] -> [BarPlot n]
mkStackedEqualBars n
yM BarLayout n
bl [[n]]
yss = BarLayout n -> [[n]] -> [BarPlot n]
forall n. Num n => BarLayout n -> [[n]] -> [BarPlot n]
mkStackedBars BarLayout n
bl [[n]]
yss'
  where
    -- Multiplier for each bar to reach the desired height.
    ms :: [n]
ms = ([n] -> n) -> [[n]] -> [n]
forall a b. (a -> b) -> [a] -> [b]
map (\[n]
ys -> n
yM n -> n -> n
forall a. Fractional a => a -> a -> a
/ [n] -> n
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [n]
ys) ([[n]] -> [n]) -> [[n]] -> [n]
forall a b. (a -> b) -> a -> b
$ [[n]] -> [[n]]
forall a. [[a]] -> [[a]]
List.transpose [[n]]
yss

    -- Normalise each data set by multiplying it with the normalising
    -- factor.
    yss' :: [[n]]
yss' = ([n] -> [n]) -> [[n]] -> [[n]]
forall a b. (a -> b) -> [a] -> [b]
map ((n -> n -> n) -> [n] -> [n] -> [n]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith n -> n -> n
forall a. Num a => a -> a -> a
(*) [n]
ms) [[n]]
yss

-- | Make bars that are grouped together. Each group of bars is treated
--   as a single bar when using the 'BarPlotsOpts'. There is an addition
--   parameter to adjust the width of each individual bar.
mkGroupedBars
  :: Fractional n
  => n -- ^ width factor of individual bars (1 = touching)
  -> BarLayout n
  -> [[n]]
  -> [BarPlot n]
mkGroupedBars :: forall n. Fractional n => n -> BarLayout n -> [[n]] -> [BarPlot n]
mkGroupedBars n
w BarLayout n
bl [[n]]
xs =
  ((Int -> [n] -> BarPlot n) -> [[n]] -> [BarPlot n])
-> [[n]] -> (Int -> [n] -> BarPlot n) -> [BarPlot n]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Int -> [n] -> BarPlot n) -> [[n]] -> [BarPlot n]
forall i (f :: * -> *) a b.
FunctorWithIndex i f =>
(i -> a -> b) -> f a -> f b
imap [[n]]
xs ((Int -> [n] -> BarPlot n) -> [BarPlot n])
-> (Int -> [n] -> BarPlot n) -> [BarPlot n]
forall a b. (a -> b) -> a -> b
$ \Int
i [n]
ns ->
    BarLayout n -> [n] -> BarPlot n
forall (f :: * -> *) n.
(Foldable f, Num n) =>
BarLayout n -> f n -> BarPlot n
mkBars
      BarLayout n
bl { bStart :: n
bStart = n
start' n -> n -> n
forall a. Num a => a -> a -> a
+ n
width' n -> n -> n
forall a. Num a => a -> a -> a
* Int -> n
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i
         , bWidth :: n
bWidth = n
width' n -> n -> n
forall a. Num a => a -> a -> a
* n
w
         }
      [n]
ns
  where
    n :: n
n = Int -> n
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> n) -> Int -> n
forall a b. (a -> b) -> a -> b
$ [[n]] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[n]]
xs
    -- start' is such that middle of the middle bar is now at
    -- barOptsStart bo
    start' :: n
start' = BarLayout n -> n
forall n. BarLayout n -> n
bStart BarLayout n
bl n -> n -> n
forall a. Num a => a -> a -> a
- (n
n n -> n -> n
forall a. Num a => a -> a -> a
- n
1) n -> n -> n
forall a. Num a => a -> a -> a
* n
width' n -> n -> n
forall a. Fractional a => a -> a -> a
/ n
2
    width' :: n
width' = BarLayout n -> n
forall n. BarLayout n -> n
bWidth BarLayout n
bl n -> n -> n
forall a. Fractional a => a -> a -> a
/ n
n

-- temporary functions that will be in next lib release

_reflectionXY :: (Additive v, R2 v, Num n) => Transformation v n
_reflectionXY :: forall (v :: * -> *) n.
(Additive v, R2 v, Num n) =>
Transformation v n
_reflectionXY = (v n :-: v n) -> Transformation v n
forall (v :: * -> *) n.
(Additive v, Num n) =>
(v n :-: v n) -> Transformation v n
fromSymmetric ((v n :-: v n) -> Transformation v n)
-> (v n :-: v n) -> Transformation v n
forall a b. (a -> b) -> a -> b
$ ((V2 n -> Identity (V2 n)) -> v n -> Identity (v n)
forall (t :: * -> *) a. R2 t => Lens' (t a) (V2 a)
_xy ((V2 n -> Identity (V2 n)) -> v n -> Identity (v n))
-> (V2 n -> V2 n) -> v n -> v n
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Getting (V2 n) (V2 n) (V2 n) -> V2 n -> V2 n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (V2 n) (V2 n) (V2 n)
forall (t :: * -> *) a. R2 t => Lens' (t a) (V2 a)
_yx) (v n -> v n) -> (v n -> v n) -> v n :-: v n
forall u v. (u -> v) -> (v -> u) -> u :-: v
<-> ((V2 n -> Identity (V2 n)) -> v n -> Identity (v n)
forall (t :: * -> *) a. R2 t => Lens' (t a) (V2 a)
_xy ((V2 n -> Identity (V2 n)) -> v n -> Identity (v n))
-> (V2 n -> V2 n) -> v n -> v n
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Getting (V2 n) (V2 n) (V2 n) -> V2 n -> V2 n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (V2 n) (V2 n) (V2 n)
forall (t :: * -> *) a. R2 t => Lens' (t a) (V2 a)
_yx)

_reflectXY :: (InSpace v n t, R2 v, Transformable t) => t -> t
_reflectXY :: forall (v :: * -> *) n t.
(InSpace v n t, R2 v, Transformable t) =>
t -> t
_reflectXY = Transformation (V t) (N t) -> t -> t
forall t. Transformable t => Transformation (V t) (N t) -> t -> t
transform Transformation (V t) (N t)
forall (v :: * -> *) n.
(Additive v, R2 v, Num n) =>
Transformation v n
_reflectionXY

----------------------------------------------------------------------------------
-- Single bar state API
----------------------------------------------------------------------------------

-- | A add 'BarPlot' to an 'Axis'.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_barExample.svg#diagram=barExample&height=400>>
--
-- > import Plots
-- > barAxis :: Axis B V2 Double
-- > barAxis = r2Axis &~ do
-- >   yMin ?= 0
-- >   hide majorGridLines
-- >   barPlot [13.5, 3.0, 6.9, 7.2, 4.6] $ do
-- >     vertical .= True
-- >     barWidth //= 2
--
-- > barExample = renderAxis barAxis
barPlot
  :: (MonadState (Axis b V2 n) m,
      Plotable (BarPlot n) b,
      F.Foldable f)
  => f n                           -- ^ bar heights
  -> State (Plot (BarPlot n) b) () -- ^ changes to the bars
  -> m ()                          -- ^ changes to the 'Axis'
barPlot :: forall b n (m :: * -> *) (f :: * -> *).
(MonadState (Axis b V2 n) m, Plotable (BarPlot n) b, Foldable f) =>
f n -> State (Plot (BarPlot n) b) () -> m ()
barPlot f n
ns = BarPlot n -> State (Plot (BarPlot n) b) () -> m ()
forall (c :: * -> *) n p b (m :: * -> *).
(InSpace (BaseSpace c) n p, MonadState (Axis b c n) m,
 Plotable p b) =>
p -> State (Plot p b) () -> m ()
addPlotable (BarLayout n -> f n -> BarPlot n
forall (f :: * -> *) n.
(Foldable f, Num n) =>
BarLayout n -> f n -> BarPlot n
mkBars BarLayout n
forall a. Default a => a
def f n
ns)

-- | Simple version of 'barPlot' without any modification to the 'Plot'.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_barExample'.svg#diagram=barExample'&height=400>>
--
-- > import Plots
-- > barAxis' :: Axis B V2 Double
-- > barAxis' = r2Axis &~ do
-- >   xMin ?= 0
-- >   hide (yAxis . majorGridLines)
-- >   barPlot' [13.5, 3.0, 6.9, 7.2, 4.6]
--
-- > barExample' = renderAxis barAxis'
barPlot'
  :: (MonadState (Axis b V2 n) m,
      Plotable (BarPlot n) b,
      F.Foldable f)
  => f n  -- ^ bar heights
  -> m () -- ^ changes to the 'Axis'
barPlot' :: forall b n (m :: * -> *) (f :: * -> *).
(MonadState (Axis b V2 n) m, Plotable (BarPlot n) b, Foldable f) =>
f n -> m ()
barPlot' f n
ns = BarPlot n -> m ()
forall (v :: * -> *) n p b (m :: * -> *).
(InSpace (BaseSpace v) n p, MonadState (Axis b v n) m,
 Plotable p b) =>
p -> m ()
addPlotable' (BarLayout n -> f n -> BarPlot n
forall (f :: * -> *) n.
(Foldable f, Num n) =>
BarLayout n -> f n -> BarPlot n
mkBars BarLayout n
forall a. Default a => a
def f n
ns)

-- | A add 'BarPlot' to an 'Axis' while naming the bars.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_namedBarExample.svg#diagram=namedBarExample&height=400>>
--
-- > import Plots
-- > namedBarAxis :: Axis B V2 Double
-- > namedBarAxis = r2Axis &~ do
-- >   yMin ?= 0
-- >   hide (xAxis . majorGridLines)
-- >   namedBarPlot [("eggs", 12), ("bacon", 5), ("sausage", 9), ("beans", 3)] $ do
-- >     vertical .= True
-- >     barWidth //= 2
-- >
-- > namedBarExample = renderAxis namedBarAxis
namedBarPlot
  :: (MonadState (Axis b V2 n) m,
      Plotable (BarPlot n) b,
      F.Foldable f)
  => f (String,n)                  -- ^ bar heights with name
  -> State (Plot (BarPlot n) b) () -- ^ changes to the bars
  -> m ()                          -- ^ changes to the 'Axis'
namedBarPlot :: forall b n (m :: * -> *) (f :: * -> *).
(MonadState (Axis b V2 n) m, Plotable (BarPlot n) b, Foldable f) =>
f (String, n) -> State (Plot (BarPlot n) b) () -> m ()
namedBarPlot f (String, n)
d State (Plot (BarPlot n) b) ()
s = do
  Plot (BarPlot n) b -> m ()
forall (c :: * -> *) n p b (m :: * -> *).
(InSpace (BaseSpace c) n p, MonadState (Axis b c n) m,
 Plotable p b) =>
Plot p b -> m ()
addPlot Plot (BarPlot n) b
bp
  BarLayout n -> [String] -> m ()
forall b n (m :: * -> *).
(MonadState (Axis b V2 n) m, Fractional n) =>
BarLayout n -> [String] -> m ()
barLayoutAxisLabels (Plot (BarPlot n) b
bp Plot (BarPlot n) b
-> Getting (BarLayout n) (Plot (BarPlot n) b) (BarLayout n)
-> BarLayout n
forall s a. s -> Getting a s a -> a
^. Getting (BarLayout n) (Plot (BarPlot n) b) (BarLayout n)
forall a. HasBarLayout a => Lens' a (BarLayout (N a))
barLayout) [String]
nms
  where
    ([String]
nms, [n]
xs) = [(String, n)] -> ([String], [n])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(String, n)] -> ([String], [n]))
-> [(String, n)] -> ([String], [n])
forall a b. (a -> b) -> a -> b
$ f (String, n) -> [(String, n)]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList f (String, n)
d
    bp :: Plot (BarPlot n) b
bp = BarPlot n -> Plot (BarPlot n) b
forall p b. (Additive (V p), Num (N p)) => p -> Plot p b
mkPlot (BarLayout n -> [n] -> BarPlot n
forall (f :: * -> *) n.
(Foldable f, Num n) =>
BarLayout n -> f n -> BarPlot n
mkBars BarLayout n
forall a. Default a => a
def [n]
xs) Plot (BarPlot n) b
-> (Plot (BarPlot n) b -> Plot (BarPlot n) b) -> Plot (BarPlot n) b
forall a b. a -> (a -> b) -> b
& State (Plot (BarPlot n) b) ()
-> Plot (BarPlot n) b -> Plot (BarPlot n) b
forall s a. State s a -> s -> s
execState State (Plot (BarPlot n) b) ()
s

-- | Simple version of 'namedBarPlot' without any modification to the 'Plot'.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_namedBarExample'.svg#diagram=namedBarExample'&height=400>>
--
-- > import Plots
-- > namedBarAxis' :: Axis B V2 Double
-- > namedBarAxis' = r2Axis &~ do
-- >   xMin ?= 0
-- >   hide majorGridLines
-- >   namedBarPlot' [("eggs", 12), ("bacon", 5), ("sausage", 9), ("beans", 3)]
--
-- > namedBarExample' = renderAxis namedBarAxis'
namedBarPlot'
  :: (MonadState (Axis b V2 n) m,
      Plotable (BarPlot n) b,
      F.Foldable f)
  => f (String,n)  -- ^ bar heights with name
  -> m ()          -- ^ add plot to the 'Axis'
namedBarPlot' :: forall b n (m :: * -> *) (f :: * -> *).
(MonadState (Axis b V2 n) m, Plotable (BarPlot n) b, Foldable f) =>
f (String, n) -> m ()
namedBarPlot' f (String, n)
ns = f (String, n) -> State (Plot (BarPlot n) b) () -> m ()
forall b n (m :: * -> *) (f :: * -> *).
(MonadState (Axis b V2 n) m, Plotable (BarPlot n) b, Foldable f) =>
f (String, n) -> State (Plot (BarPlot n) b) () -> m ()
namedBarPlot f (String, n)
ns (() -> State (Plot (BarPlot n) b) ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())

-- | Same as 'barPlot' but with lower and upper bounds for the bars.
floatingBarPlot
  :: (MonadState (Axis b V2 n) m,
      Plotable (BarPlot n) b,
      F.Foldable f)
  => f (n,n) -- ^ bar limits
  -> State (Plot (BarPlot n) b) () -- ^ changes to the bars
  -> m ()
floatingBarPlot :: forall b n (m :: * -> *) (f :: * -> *).
(MonadState (Axis b V2 n) m, Plotable (BarPlot n) b, Foldable f) =>
f (n, n) -> State (Plot (BarPlot n) b) () -> m ()
floatingBarPlot f (n, n)
ns = BarPlot n -> State (Plot (BarPlot n) b) () -> m ()
forall (c :: * -> *) n p b (m :: * -> *).
(InSpace (BaseSpace c) n p, MonadState (Axis b c n) m,
 Plotable p b) =>
p -> State (Plot p b) () -> m ()
addPlotable (BarLayout n -> f (n, n) -> BarPlot n
forall (f :: * -> *) n.
Foldable f =>
BarLayout n -> f (n, n) -> BarPlot n
mkFloatingBars BarLayout n
forall a. Default a => a
def f (n, n)
ns)

------------------------------------------------------------------------
-- Multi bar state API
------------------------------------------------------------------------

-- Multi bar state -----------------------------------------------------

-- | The 'MultiBarState' is used to set the various options available
--   when building multiple bar plots together. The main functions used
--   to modify this state:
--
--   * To choose the way the bars are grouped together choose one of
--
--       * 'groupedBars'      - Together in grouped (the default)
--       * 'stackedBars'      - On on top of another
--       * 'stackedEqualBars' - 'stackedBars' with the same height
--       * 'runningBars'      - each group of bars follows the last
--
--   * Modify the 'PlotOptions' and 'PlotStyle' of groups of bars with
--     'onBars'.
--
--   * Modify the layout of the (groups of) bars with
--
--       * 'orientation' - Horizontal or vertical bars
--       * 'barWidth'    - Width of each (group of) bar(s)
--       * 'barSpacing'  - Space between each (group of) bar(s)
--       * 'barStart'    - Start of centre of first bar
--
--   * Add labels to each (group of) bars with 'labelBars'.
--
data MultiBarState b n a = MultiBarState
  { forall b n a. MultiBarState b n a -> BarLayout n
mbsLayout :: BarLayout n
    -- ^ options for building bar plots

  , forall b n a. MultiBarState b n a -> [(a, Endo (PlotMods b V2 n))]
mbsMods :: [(a, Endo (PlotMods b V2 n))]
    -- ^ the data along with an adjustment to the plot properties

  , forall b n a. MultiBarState b n a -> [String]
mbsLabels  :: [String]
    -- ^ labels to be placed at the bottom of each bar

  , forall b n a.
MultiBarState b n a -> BarLayout n -> [[n]] -> [BarPlot n]
mbsBarFun :: BarLayout n -> [[n]] -> [BarPlot n]
    -- ^ function used to build bar plots
  }

type instance N (MultiBarState b n a) = n

instance HasOrientation (MultiBarState b n a) where
  orientation :: Lens' (MultiBarState b n a) Orientation
orientation = (BarLayout n -> f (BarLayout n))
-> MultiBarState b n a -> f (MultiBarState b n a)
forall a. HasBarLayout a => Lens' a (BarLayout (N a))
barLayout ((BarLayout n -> f (BarLayout n))
 -> MultiBarState b n a -> f (MultiBarState b n a))
-> ((Orientation -> f Orientation)
    -> BarLayout n -> f (BarLayout n))
-> (Orientation -> f Orientation)
-> MultiBarState b n a
-> f (MultiBarState b n a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Orientation -> f Orientation) -> BarLayout n -> f (BarLayout n)
forall a. HasOrientation a => Lens' a Orientation
orientation

instance HasBarLayout (MultiBarState b n a) where
  barLayout :: Lens' (MultiBarState b n a) (BarLayout (N (MultiBarState b n a)))
barLayout = (MultiBarState b n a -> BarLayout n)
-> (MultiBarState b n a -> BarLayout n -> MultiBarState b n a)
-> Lens
     (MultiBarState b n a)
     (MultiBarState b n a)
     (BarLayout n)
     (BarLayout n)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens MultiBarState b n a -> BarLayout n
forall b n a. MultiBarState b n a -> BarLayout n
mbsLayout (\MultiBarState b n a
mbs BarLayout n
l -> MultiBarState b n a
mbs {mbsLayout :: BarLayout n
mbsLayout = BarLayout n
l})

-- > import Plots
--
-- > groupedExample s = r2Axis &~ do
-- >   yMin ?= 0
-- >   hide (xAxis . majorGridLines)
-- >   xLabel .= "breakfast item"
-- >   hide minorTicks
-- >   multiBars sortedData snd $ do
-- >     vertical .= True
-- >     barWidth //= 2
-- >     labelBars (map fst breakfastData)
-- >     onBars $ \(nm,_) -> key nm
-- >     s
-- >
-- >   -- show y values without decimal point
-- >   yAxis . tickLabelFunction .= atMajorTicks (show . round)
-- >   -- we should really force all major ticks to like on integers too
--
-- > groupedBarsExample  = renderAxis $ groupedExample groupedBars
-- > groupedBarsExample' = renderAxis $ groupedExample (groupedBars' 0.7)
-- > stackedBarsExample  = renderAxis $ groupedExample  stackedBars
-- > stackedEqualBarsExample = renderAxis $ groupedExample (stackedEqualBars 10)
-- > runningBarsExample  = renderAxis $ groupedExample $ do
-- >   runningBars
-- >   labelBars (map fst breakfastData ++ map fst breakfastData)

-- Adding to axis ------------------------------------------------------

multiFun :: Lens' (MultiBarState b n a) (BarLayout n -> [[n]] -> [BarPlot n])
multiFun :: forall b n a.
Lens' (MultiBarState b n a) (BarLayout n -> [[n]] -> [BarPlot n])
multiFun = (MultiBarState b n a -> BarLayout n -> [[n]] -> [BarPlot n])
-> (MultiBarState b n a
    -> (BarLayout n -> [[n]] -> [BarPlot n]) -> MultiBarState b n a)
-> Lens
     (MultiBarState b n a)
     (MultiBarState b n a)
     (BarLayout n -> [[n]] -> [BarPlot n])
     (BarLayout n -> [[n]] -> [BarPlot n])
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens MultiBarState b n a -> BarLayout n -> [[n]] -> [BarPlot n]
forall b n a.
MultiBarState b n a -> BarLayout n -> [[n]] -> [BarPlot n]
mbsBarFun (\MultiBarState b n a
mbs BarLayout n -> [[n]] -> [BarPlot n]
f -> MultiBarState b n a
mbs {mbsBarFun :: BarLayout n -> [[n]] -> [BarPlot n]
mbsBarFun = BarLayout n -> [[n]] -> [BarPlot n]
f})

-- | Bars that are grouped together such that each group is a single
--   'barWidth'. The bars in a group are touching, see groupedBars' to
--   reduce the width of individual bars.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_groupedBarsExample.svg#diagram=groupedBarsExample&height=400>>

groupedBars :: Fractional n => State (MultiBarState b n a) ()
groupedBars :: forall n b a. Fractional n => State (MultiBarState b n a) ()
groupedBars = n -> State (MultiBarState b n a) ()
forall n b a. Fractional n => n -> State (MultiBarState b n a) ()
groupedBars' n
1

-- | Bars that are grouped together such that each group is a single
--   'barWidth'. The parameter is the multiplier for the width of
--   individual bars, where @'groupedBars' 1 = groupedBars@ corresponds
--   to bars in a group touching. reduce the width of individual bars.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_groupedBarsExample'.svg#diagram=groupedBarsExample'&height=400>>
--
groupedBars' :: Fractional n => n -> State (MultiBarState b n a) ()
groupedBars' :: forall n b a. Fractional n => n -> State (MultiBarState b n a) ()
groupedBars' n
n = ((BarLayout n -> [[n]] -> [BarPlot n])
 -> Identity (BarLayout n -> [[n]] -> [BarPlot n]))
-> MultiBarState b n a -> Identity (MultiBarState b n a)
forall b n a.
Lens' (MultiBarState b n a) (BarLayout n -> [[n]] -> [BarPlot n])
multiFun (((BarLayout n -> [[n]] -> [BarPlot n])
  -> Identity (BarLayout n -> [[n]] -> [BarPlot n]))
 -> MultiBarState b n a -> Identity (MultiBarState b n a))
-> (BarLayout n -> [[n]] -> [BarPlot n])
-> StateT (MultiBarState b n a) Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= n -> BarLayout n -> [[n]] -> [BarPlot n]
forall n. Fractional n => n -> BarLayout n -> [[n]] -> [BarPlot n]
mkGroupedBars n
n

-- | Bars stacked on top of each other.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_stackedBarsExample.svg#diagram=stackedBarsExample&height=400>>
--
stackedBars :: Num n => State (MultiBarState b n a) ()
stackedBars :: forall n b a. Num n => State (MultiBarState b n a) ()
stackedBars = ((BarLayout n -> [[n]] -> [BarPlot n])
 -> Identity (BarLayout n -> [[n]] -> [BarPlot n]))
-> MultiBarState b n a -> Identity (MultiBarState b n a)
forall b n a.
Lens' (MultiBarState b n a) (BarLayout n -> [[n]] -> [BarPlot n])
multiFun (((BarLayout n -> [[n]] -> [BarPlot n])
  -> Identity (BarLayout n -> [[n]] -> [BarPlot n]))
 -> MultiBarState b n a -> Identity (MultiBarState b n a))
-> (BarLayout n -> [[n]] -> [BarPlot n])
-> StateT (MultiBarState b n a) Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= BarLayout n -> [[n]] -> [BarPlot n]
forall n. Num n => BarLayout n -> [[n]] -> [BarPlot n]
mkStackedBars

-- | Bars stacked on top of each other where every bar is the given
--   height.
--
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_stackedEqualBarsExample.svg#diagram=stackedEqualBarsExample&height=400>>
--
stackedEqualBars :: Fractional n => n -> State (MultiBarState b n a) ()
stackedEqualBars :: forall n b a. Fractional n => n -> State (MultiBarState b n a) ()
stackedEqualBars n
n = ((BarLayout n -> [[n]] -> [BarPlot n])
 -> Identity (BarLayout n -> [[n]] -> [BarPlot n]))
-> MultiBarState b n a -> Identity (MultiBarState b n a)
forall b n a.
Lens' (MultiBarState b n a) (BarLayout n -> [[n]] -> [BarPlot n])
multiFun (((BarLayout n -> [[n]] -> [BarPlot n])
  -> Identity (BarLayout n -> [[n]] -> [BarPlot n]))
 -> MultiBarState b n a -> Identity (MultiBarState b n a))
-> (BarLayout n -> [[n]] -> [BarPlot n])
-> StateT (MultiBarState b n a) Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= n -> BarLayout n -> [[n]] -> [BarPlot n]
forall n. Fractional n => n -> BarLayout n -> [[n]] -> [BarPlot n]
mkStackedEqualBars n
n

-- | Normal 'bars' where each data set follows the last.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_runningBarsExample.svg#diagram=runningBarsExample&height=400>>
--
runningBars :: Num n => State (MultiBarState b n a) ()
runningBars :: forall n b a. Num n => State (MultiBarState b n a) ()
runningBars = ((BarLayout n -> [[n]] -> [BarPlot n])
 -> Identity (BarLayout n -> [[n]] -> [BarPlot n]))
-> MultiBarState b n a -> Identity (MultiBarState b n a)
forall b n a.
Lens' (MultiBarState b n a) (BarLayout n -> [[n]] -> [BarPlot n])
multiFun (((BarLayout n -> [[n]] -> [BarPlot n])
  -> Identity (BarLayout n -> [[n]] -> [BarPlot n]))
 -> MultiBarState b n a -> Identity (MultiBarState b n a))
-> (BarLayout n -> [[n]] -> [BarPlot n])
-> StateT (MultiBarState b n a) Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= \BarLayout n
l [[n]]
xs -> BarLayout n -> [[(n, n)]] -> [BarPlot n]
forall n. Num n => BarLayout n -> [[(n, n)]] -> [BarPlot n]
mkRunningBars BarLayout n
l (([n] -> [(n, n)]) -> [[n]] -> [[(n, n)]]
forall a b. (a -> b) -> [a] -> [b]
map ((n -> (n, n)) -> [n] -> [(n, n)]
forall a b. (a -> b) -> [a] -> [b]
map (n
0,)) [[n]]
xs)

-- | Construct multiple bars, grouped together. See 'MultiBarState' for
--   details on how to customise how the bars are drawn.
--
-- === __Example__
--
-- <<diagrams/src_Plots_Types_Bar_multiBarExample.svg#diagram=multiBarExample&height=400>>
--
-- > import Plots
-- > breakfastData :: [(String, V2 Double)]
-- > breakfastData = [("eggs", V2 7 5), ("bacon", V2 5 4), ("sausage", V2 2 7), ("beans", V2 2 1)]
--
-- > sortedData = [ ("girls", breakfastData^..each._2._x)
-- >              , ("boys",  breakfastData^..each._2._y)
-- >              ]
--
-- > multiBarAxis :: Axis B V2 Double
-- > multiBarAxis = r2Axis &~ do
-- >   yMin ?= 0
-- >   hide (xAxis . majorGridLines)
-- >   hide minorTicks
-- >   xLabel .= "breakfast item"
-- >   multiBars sortedData snd $ do
-- >     vertical .= True
-- >     barWidth //= 2
-- >     labelBars (map fst breakfastData)
-- >     onBars $ \(nm,_) -> key nm
-- >
-- >   -- show y values without decimal point
-- >   yAxis . tickLabelFunction .= atMajorTicks (show . round)
-- >   -- we should really force all major ticks to like on integers too
--
-- > multiBarExample = renderAxis multiBarAxis
multiBars
  :: (MonadState (Axis b V2 n) m,
      Plotable (BarPlot n) b,
      F.Foldable f,
      F.Foldable g)
  => f a                            -- ^ data for multi plot
  -> (a -> g n)                     -- ^ extract bar heights from each data set
  -> State (MultiBarState b n a) () -- ^ state to make changes to the plot
  -> m ()                           -- ^ changes to the 'Axis'
multiBars :: forall b n (m :: * -> *) (f :: * -> *) (g :: * -> *) a.
(MonadState (Axis b V2 n) m, Plotable (BarPlot n) b, Foldable f,
 Foldable g) =>
f a -> (a -> g n) -> State (MultiBarState b n a) () -> m ()
multiBars (f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList -> [a]
as) a -> g n
f State (MultiBarState b n a) ()
st = do
  -- add the plots
  [(BarPlot n, Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n))))]
-> ((BarPlot n, Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n))))
    -> m ())
-> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
F.forM_ [(BarPlot n, Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n))))]
propertiedBars (((BarPlot n, Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n))))
  -> m ())
 -> m ())
-> ((BarPlot n, Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n))))
    -> m ())
-> m ()
forall a b. (a -> b) -> a -> b
$ \(BarPlot n
b,Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))
endo) ->
    BarPlot n -> State (Plot (BarPlot n) b) () -> m ()
forall (c :: * -> *) n p b (m :: * -> *).
(InSpace (BaseSpace c) n p, MonadState (Axis b c n) m,
 Plotable p b) =>
p -> State (Plot p b) () -> m ()
addPlotable BarPlot n
b (State (Plot (BarPlot n) b) () -> m ())
-> State (Plot (BarPlot n) b) () -> m ()
forall a b. (a -> b) -> a -> b
$ (PlotMods b (V (BarPlot n)) (N (BarPlot n))
 -> Identity (PlotMods b (V (BarPlot n)) (N (BarPlot n))))
-> Plot (BarPlot n) b -> Identity (Plot (BarPlot n) b)
forall p b. Lens' (Plot p b) (PlotMods b (V p) (N p))
plotMods ((PlotMods b (V (BarPlot n)) (N (BarPlot n))
  -> Identity (PlotMods b (V (BarPlot n)) (N (BarPlot n))))
 -> Plot (BarPlot n) b -> Identity (Plot (BarPlot n) b))
-> (PlotMods b (V (BarPlot n)) (N (BarPlot n))
    -> PlotMods b (V (BarPlot n)) (N (BarPlot n)))
-> State (Plot (BarPlot n) b) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))
-> PlotMods b (V (BarPlot n)) (N (BarPlot n))
-> PlotMods b (V (BarPlot n)) (N (BarPlot n))
forall a. Endo a -> a -> a
appEndo Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))
endo

  -- label bars on axis if necessary
  BarLayout n -> [String] -> m ()
forall b n (m :: * -> *).
(MonadState (Axis b V2 n) m, Fractional n) =>
BarLayout n -> [String] -> m ()
barLayoutAxisLabels (MultiBarState b n a
bs MultiBarState b n a
-> Getting (BarLayout n) (MultiBarState b n a) (BarLayout n)
-> BarLayout n
forall s a. s -> Getting a s a -> a
^. Getting (BarLayout n) (MultiBarState b n a) (BarLayout n)
forall a. HasBarLayout a => Lens' a (BarLayout (N a))
barLayout) (MultiBarState b n a
bs MultiBarState b n a
-> Getting [String] (MultiBarState b n a) [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] (MultiBarState b n a) [String]
forall a. HasLabels a => Lens' a [String]
labels)
  where
    -- bars
    propertiedBars :: [(BarPlot n, Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n))))]
propertiedBars = [BarPlot n]
-> [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))]
-> [(BarPlot n, Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n))))]
forall a b. [a] -> [b] -> [(a, b)]
zip [BarPlot n]
barPlots [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))]
endos
    barPlots :: [BarPlot n]
barPlots = MultiBarState b n a -> BarLayout n -> [[n]] -> [BarPlot n]
forall b n a.
MultiBarState b n a -> BarLayout n -> [[n]] -> [BarPlot n]
mbsBarFun MultiBarState b n a
bs (MultiBarState b n a
bs MultiBarState b n a
-> Getting (BarLayout n) (MultiBarState b n a) (BarLayout n)
-> BarLayout n
forall s a. s -> Getting a s a -> a
^. Getting (BarLayout n) (MultiBarState b n a) (BarLayout n)
forall a. HasBarLayout a => Lens' a (BarLayout (N a))
barLayout) ([[n]] -> [BarPlot n]) -> [[n]] -> [BarPlot n]
forall a b. (a -> b) -> a -> b
$ (a -> [n]) -> [a] -> [[n]]
forall a b. (a -> b) -> [a] -> [b]
map (g n -> [n]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList (g n -> [n]) -> (a -> g n) -> a -> [n]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> g n
f) [a]
as

    -- data and modifiers
    endos :: [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))]
endos = MultiBarState b n a -> [(a, Endo (PlotMods b V2 n))]
forall b n a. MultiBarState b n a -> [(a, Endo (PlotMods b V2 n))]
mbsMods MultiBarState b n a
bs [(a, Endo (PlotMods b V2 n))]
-> Getting
     (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
     [(a, Endo (PlotMods b V2 n))]
     (Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n))))
-> [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. ((a, Endo (PlotMods b V2 n))
 -> Const
      (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
      (a, Endo (PlotMods b V2 n)))
-> [(a, Endo (PlotMods b V2 n))]
-> Const
     (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
     [(a, Endo (PlotMods b V2 n))]
forall s t a b. Each s t a b => Traversal s t a b
each (((a, Endo (PlotMods b V2 n))
  -> Const
       (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
       (a, Endo (PlotMods b V2 n)))
 -> [(a, Endo (PlotMods b V2 n))]
 -> Const
      (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
      [(a, Endo (PlotMods b V2 n))])
-> ((Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))
     -> Const
          (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
          (Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))))
    -> (a, Endo (PlotMods b V2 n))
    -> Const
         (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
         (a, Endo (PlotMods b V2 n)))
-> Getting
     (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
     [(a, Endo (PlotMods b V2 n))]
     (Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n))))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))
 -> Const
      (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
      (Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))))
-> (a, Endo (PlotMods b V2 n))
-> Const
     (Endo [Endo (PlotMods b (V (BarPlot n)) (N (BarPlot n)))])
     (a, Endo (PlotMods b V2 n))
forall s t a b. Field2 s t a b => Lens s t a b
_2

    -- bar state
    bs :: MultiBarState b n a
bs  = State (MultiBarState b n a) ()
-> MultiBarState b n a -> MultiBarState b n a
forall s a. State s a -> s -> s
execState State (MultiBarState b n a) ()
st MultiBarState b n a
bs0
    bs0 :: MultiBarState b n a
bs0 = MultiBarState
      { mbsLayout :: BarLayout n
mbsLayout = BarLayout n
forall a. Default a => a
def
      , mbsMods :: [(a, Endo (PlotMods b V2 n))]
mbsMods   = (a -> (a, Endo (PlotMods b V2 n)))
-> [a] -> [(a, Endo (PlotMods b V2 n))]
forall a b. (a -> b) -> [a] -> [b]
map (\a
a -> (a
a, Endo (PlotMods b V2 n)
forall a. Monoid a => a
mempty)) [a]
as
      , mbsLabels :: [String]
mbsLabels = []
      , mbsBarFun :: BarLayout n -> [[n]] -> [BarPlot n]
mbsBarFun = n -> BarLayout n -> [[n]] -> [BarPlot n]
forall n. Fractional n => n -> BarLayout n -> [[n]] -> [BarPlot n]
mkGroupedBars n
1
      }

-- | Place labels under the centre of each bar using the 'BarLayout' by
--   changing that 'axisTickLabels', using the provided string in order.
barLayoutAxisLabels
  :: (MonadState (Axis b V2 n) m, Fractional n)
  => BarLayout n -> [String] -> m ()
barLayoutAxisLabels :: forall b n (m :: * -> *).
(MonadState (Axis b V2 n) m, Fractional n) =>
BarLayout n -> [String] -> m ()
barLayoutAxisLabels BarLayout n
bl [String]
ls =
  Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
ls) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
    (V2 (SingleAxis b (BaseSpace V2) n)
 -> Identity (V2 (SingleAxis b (BaseSpace V2) n)))
-> Axis b V2 n -> Identity (Axis b V2 n)
forall (v :: * -> *) (c :: * -> *) (c' :: * -> *) b n.
(v ~ BaseSpace c, v ~ BaseSpace c') =>
Lens
  (Axis b c n)
  (Axis b c' n)
  (c (SingleAxis b v n))
  (c' (SingleAxis b v n))
axes ((V2 (SingleAxis b (BaseSpace V2) n)
  -> Identity (V2 (SingleAxis b (BaseSpace V2) n)))
 -> Axis b V2 n -> Identity (Axis b V2 n))
-> ((SingleAxis b (BaseSpace V2) n
     -> Identity (SingleAxis b (BaseSpace V2) n))
    -> V2 (SingleAxis b (BaseSpace V2) n)
    -> Identity (V2 (SingleAxis b (BaseSpace V2) n)))
-> (SingleAxis b (BaseSpace V2) n
    -> Identity (SingleAxis b (BaseSpace V2) n))
-> Axis b V2 n
-> Identity (Axis b V2 n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BarLayout n
-> ((SingleAxis b (BaseSpace V2) n
     -> Identity (SingleAxis b (BaseSpace V2) n))
    -> V2 (SingleAxis b (BaseSpace V2) n)
    -> Identity (V2 (SingleAxis b (BaseSpace V2) n)))
-> ((SingleAxis b (BaseSpace V2) n
     -> Identity (SingleAxis b (BaseSpace V2) n))
    -> V2 (SingleAxis b (BaseSpace V2) n)
    -> Identity (V2 (SingleAxis b (BaseSpace V2) n)))
-> (SingleAxis b (BaseSpace V2) n
    -> Identity (SingleAxis b (BaseSpace V2) n))
-> V2 (SingleAxis b (BaseSpace V2) n)
-> Identity (V2 (SingleAxis b (BaseSpace V2) n))
forall o a. HasOrientation o => o -> a -> a -> a
orient BarLayout n
bl (SingleAxis b (BaseSpace V2) n
 -> Identity (SingleAxis b (BaseSpace V2) n))
-> V2 (SingleAxis b (BaseSpace V2) n)
-> Identity (V2 (SingleAxis b (BaseSpace V2) n))
forall (t :: * -> *) a. R2 t => Lens' (t a) a
_y (SingleAxis b (BaseSpace V2) n
 -> Identity (SingleAxis b (BaseSpace V2) n))
-> V2 (SingleAxis b (BaseSpace V2) n)
-> Identity (V2 (SingleAxis b (BaseSpace V2) n))
forall (t :: * -> *) a. R1 t => Lens' (t a) a
_x ((SingleAxis b (BaseSpace V2) n
  -> Identity (SingleAxis b (BaseSpace V2) n))
 -> Axis b V2 n -> Identity (Axis b V2 n))
-> State (SingleAxis b (BaseSpace V2) n) () -> m ()
forall s (m :: * -> *) b a.
MonadState s m =>
ASetter' s b -> State b a -> m ()
&= do
      ([N (SingleAxis b V2 n)] -> Identity [N (BarLayout n)])
-> SingleAxis b V2 n -> Identity (SingleAxis b V2 n)
forall (f :: * -> *) a.
(HasMajorTicks f a, Settable f) =>
LensLike' f a [N a]
majorTickPositions  (([N (SingleAxis b V2 n)] -> Identity [N (BarLayout n)])
 -> SingleAxis b V2 n -> Identity (SingleAxis b V2 n))
-> [N (BarLayout n)] -> State (SingleAxis b (BaseSpace V2) n) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [N (BarLayout n)]
xs
      LensLike'
  Identity
  (SingleAxis b V2 n)
  (MinorTicks (V (SingleAxis b V2 n)) (N (SingleAxis b V2 n)))
forall (f :: * -> *) a.
HasMinorTicks f a =>
LensLike' f a (MinorTicks (V a) (N a))
minorTicks LensLike'
  Identity
  (SingleAxis b V2 n)
  (MinorTicks (V (SingleAxis b V2 n)) (N (SingleAxis b V2 n)))
-> ((Bool -> Identity Bool)
    -> MinorTicks (V (SingleAxis b V2 n)) (N (SingleAxis b V2 n))
    -> Identity
         (MinorTicks (V (SingleAxis b V2 n)) (N (SingleAxis b V2 n))))
-> (Bool -> Identity Bool)
-> SingleAxis b V2 n
-> Identity (SingleAxis b V2 n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Identity Bool)
-> MinorTicks (V (SingleAxis b V2 n)) (N (SingleAxis b V2 n))
-> Identity
     (MinorTicks (V (SingleAxis b V2 n)) (N (SingleAxis b V2 n)))
forall a. HasVisibility a => Lens' a Bool
visible ((Bool -> Identity Bool)
 -> SingleAxis b V2 n -> Identity (SingleAxis b V2 n))
-> Bool -> State (SingleAxis b (BaseSpace V2) n) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
False
      ([(N (SingleAxis b V2 n), String)]
 -> Identity [(N (BarLayout n), String)])
-> SingleAxis b V2 n -> Identity (SingleAxis b V2 n)
forall (f :: * -> *) a b.
(HasTickLabels f a b, Settable f) =>
LensLike' f a [(N a, String)]
tickLabelPositions   (([(N (SingleAxis b V2 n), String)]
  -> Identity [(N (BarLayout n), String)])
 -> SingleAxis b V2 n -> Identity (SingleAxis b V2 n))
-> [(N (BarLayout n), String)]
-> State (SingleAxis b (BaseSpace V2) n) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [N (BarLayout n)] -> [String] -> [(N (BarLayout n), String)]
forall a b. [a] -> [b] -> [(a, b)]
zip [N (BarLayout n)]
xs [String]
ls
  where
    xs :: [N (BarLayout n)]
xs = (Int -> N (BarLayout n)) -> [Int] -> [N (BarLayout n)]
forall a b. (a -> b) -> [a] -> [b]
map ((N (BarLayout n) -> N (BarLayout n) -> N (BarLayout n)
forall a. Num a => a -> a -> a
+ Getting (N (BarLayout n)) (BarLayout n) (N (BarLayout n))
-> BarLayout n -> N (BarLayout n)
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (N (BarLayout n)) (BarLayout n) (N (BarLayout n))
forall a. HasBarLayout a => Lens' a (N a)
barStart BarLayout n
bl) (N (BarLayout n) -> N (BarLayout n))
-> (Int -> N (BarLayout n)) -> Int -> N (BarLayout n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (N (BarLayout n) -> N (BarLayout n) -> N (BarLayout n)
forall a. Num a => a -> a -> a
* Getting (N (BarLayout n)) (BarLayout n) (N (BarLayout n))
-> BarLayout n -> N (BarLayout n)
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (N (BarLayout n)) (BarLayout n) (N (BarLayout n))
forall a. HasBarLayout a => Lens' a (N a)
barSpacing BarLayout n
bl) (N (BarLayout n) -> N (BarLayout n))
-> (Int -> N (BarLayout n)) -> Int -> N (BarLayout n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> N (BarLayout n)
forall a b. (Integral a, Num b) => a -> b
fromIntegral)
             [Int
0 .. [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
ls Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]

-- | Given the data for the bar, modify the properties for the bar that
--   uses that data.
--
--   Some common functions to use on the 'PlotMods':
--
--       * 'plotColour' - change the colour of the bars
--
--       * 'areaStyle' - modify the style of the bars
--
--       * 'key' - add a legend entry for that group of bars
--
onBars
  :: (a -> State (PlotMods b V2 n) ())
     -- ^ Modifier the 'PlotOptions' and 'PlotStyle' for the bars
     -- associated with the data from @a@.

  -> State (MultiBarState b n a) ()
     -- ^ Changes to each data set when executing 'multiBars'.
onBars :: forall a b n.
(a -> State (PlotMods b V2 n) ()) -> State (MultiBarState b n a) ()
onBars a -> State (PlotMods b V2 n) ()
f =
  ([(a, Endo (PlotMods b V2 n))]
 -> Identity [(a, Endo (PlotMods b V2 n))])
-> MultiBarState b n a -> Identity (MultiBarState b n a)
forall {a} {b} {n} {a} {b}.
([(a, Endo (PlotMods b V2 n))]
 -> Identity [(a, Endo (PlotMods b V2 n))])
-> MultiBarState b n a -> Identity (MultiBarState b n a)
mods (([(a, Endo (PlotMods b V2 n))]
  -> Identity [(a, Endo (PlotMods b V2 n))])
 -> MultiBarState b n a -> Identity (MultiBarState b n a))
-> (((a, Endo (PlotMods b V2 n))
     -> Identity (a, Endo (PlotMods b V2 n)))
    -> [(a, Endo (PlotMods b V2 n))]
    -> Identity [(a, Endo (PlotMods b V2 n))])
-> ((a, Endo (PlotMods b V2 n))
    -> Identity (a, Endo (PlotMods b V2 n)))
-> MultiBarState b n a
-> Identity (MultiBarState b n a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a, Endo (PlotMods b V2 n))
 -> Identity (a, Endo (PlotMods b V2 n)))
-> [(a, Endo (PlotMods b V2 n))]
-> Identity [(a, Endo (PlotMods b V2 n))]
forall (f :: * -> *) a b. Functor f => Setter (f a) (f b) a b
mapped (((a, Endo (PlotMods b V2 n))
  -> Identity (a, Endo (PlotMods b V2 n)))
 -> MultiBarState b n a -> Identity (MultiBarState b n a))
-> ((a, Endo (PlotMods b V2 n)) -> (a, Endo (PlotMods b V2 n)))
-> StateT (MultiBarState b n a) Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= \(a
a, Endo (PlotMods b V2 n)
endo) -> (a
a, Endo (PlotMods b V2 n)
endo Endo (PlotMods b V2 n)
-> Endo (PlotMods b V2 n) -> Endo (PlotMods b V2 n)
forall a. Semigroup a => a -> a -> a
<> (PlotMods b V2 n -> PlotMods b V2 n) -> Endo (PlotMods b V2 n)
forall a. (a -> a) -> Endo a
Endo (State (PlotMods b V2 n) () -> PlotMods b V2 n -> PlotMods b V2 n
forall s a. State s a -> s -> s
execState (a -> State (PlotMods b V2 n) ()
f a
a)))
  where mods :: ([(a, Endo (PlotMods b V2 n))]
 -> Identity [(a, Endo (PlotMods b V2 n))])
-> MultiBarState b n a -> Identity (MultiBarState b n a)
mods = (MultiBarState b n a -> [(a, Endo (PlotMods b V2 n))])
-> (MultiBarState b n a
    -> [(a, Endo (PlotMods b V2 n))] -> MultiBarState b n a)
-> Lens
     (MultiBarState b n a)
     (MultiBarState b n a)
     [(a, Endo (PlotMods b V2 n))]
     [(a, Endo (PlotMods b V2 n))]
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens MultiBarState b n a -> [(a, Endo (PlotMods b V2 n))]
forall b n a. MultiBarState b n a -> [(a, Endo (PlotMods b V2 n))]
mbsMods (\MultiBarState b n a
bs [(a, Endo (PlotMods b V2 n))]
d -> MultiBarState b n a
bs {mbsMods :: [(a, Endo (PlotMods b V2 n))]
mbsMods = [(a, Endo (PlotMods b V2 n))]
d})

class HasLabels a where
  labels :: Lens' a [String]

instance HasLabels (MultiBarState b n a) where
  labels :: Lens' (MultiBarState b n a) [String]
labels = (MultiBarState b n a -> [String])
-> (MultiBarState b n a -> [String] -> MultiBarState b n a)
-> Lens' (MultiBarState b n a) [String]
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens MultiBarState b n a -> [String]
forall b n a. MultiBarState b n a -> [String]
mbsLabels (\MultiBarState b n a
mbs [String]
ls -> MultiBarState b n a
mbs {mbsLabels :: [String]
mbsLabels = [String]
ls})

-- | Labels to use for each bar (or group of bars) along the axis.
labelBars :: HasLabels a => [String] -> State a ()
labelBars :: forall a. HasLabels a => [String] -> State a ()
labelBars [String]
xs = ([String] -> Identity [String]) -> a -> Identity a
forall a. HasLabels a => Lens' a [String]
labels (([String] -> Identity [String]) -> a -> Identity a)
-> [String] -> StateT a Identity ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [String]
xs