{-# LANGUAGE DeriveDataTypeable     #-}
{-# LANGUAGE FlexibleContexts       #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE TemplateHaskell        #-}
{-# LANGUAGE TypeFamilies           #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Plots.Axis.Labels
-- Copyright   :  (C) 2015-2017 Christopher Chalmers
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Christopher Chalmers
-- Stability   :  experimental
-- Portability :  non-portable
--
-- There are two kinds of labels this module deals with: The 'AxisLabel'
-- labels are placed next to an axis line. The 'TickLabels' are the
-- numbers (usually) next to each major tick on an axis line.
--
----------------------------------------------------------------------------
module Plots.Axis.Labels
  ( -- * Axis line labels
    HasAxisLabel (..)
  , AxisLabel
  , AxisLabelPosition (..)
  , AxisLabelPlacement (..)

    -- * Axis tick labels
  , TickLabels
  , HasTickLabels (..)
  , tickLabelPositions
  , atMajorTicks

    -- * Misc
  , TextFunction
  ) where

import           Control.Lens       hiding (( # ))
import           Data.Data
import           Data.Default

import           Diagrams.Prelude   hiding (view)
import           Diagrams.TwoD.Text
import           Plots.Types

-- | Function to render the axis label from a string. This is very basic
--   now and will be replace by a more sophisticated system.
type TextFunction b v n = TextAlignment n -> String -> QDiagram b v n Any

------------------------------------------------------------------------
-- Axis labels
------------------------------------------------------------------------

-- | The position of the 'AxisLabel' along the axis.
data AxisLabelPosition
   = MiddleAxisLabel
   | LowerAxisLabel
   | UpperAxisLabel

-- | Whether the 'AxisLabel' should be inside or outside the axis.
data AxisLabelPlacement
   = InsideAxisLabel
   | OutsideAxisLabel

-- | 'AxisLabel' describes the label next to each axis line. They are
--   normally set with the 'Plots.Axis.xLabel' and 'Plots.Axis.yLabel'
--   helper function:
--
-- @
-- myAxis = r2Axis &~ do
--   'Plots.Axis.xLabel' .= "time (s)"
--   'Plots.Axis.yLabel' .= "height (m)"
-- @
--
--   See 'HasAxisLabel' for more advanced settings.
data AxisLabel b v n = AxisLabel
  { forall b (v :: * -> *) n. AxisLabel b v n -> TextFunction b v n
alFun       :: TextFunction b v n
  , forall b (v :: * -> *) n. AxisLabel b v n -> String
alText      :: String
  , forall b (v :: * -> *) n. AxisLabel b v n -> Style v n
alStyle     :: Style v n
  , forall b (v :: * -> *) n. AxisLabel b v n -> n
alGap       :: n
  , forall b (v :: * -> *) n. AxisLabel b v n -> AxisLabelPosition
alPos       :: AxisLabelPosition
  , forall b (v :: * -> *) n. AxisLabel b v n -> AxisLabelPlacement
alPlacement :: AxisLabelPlacement
  , forall b (v :: * -> *) n. AxisLabel b v n -> Bool
alVisible   :: Bool
  }

type instance V (AxisLabel b v n) = v
type instance N (AxisLabel b v n) = n

class HasAxisLabel f a b | a -> b where
  -- | The options for the label of the axis. This can be used on
  --   various levels of the axis:
  --
  -- @
  -- 'axisLabel' :: 'Traversal'' ('Axis' b c n)       ('AxisLabel' ('BaseSpace' c) n)
  -- 'axisLabel' :: 'Lens''      ('SingleAxis' b v n) ('AxisLabel' v n)
  -- 'axisLabel' :: 'Lens''      ('AxisLabel' v n)    ('AxisLabel' v n)
  -- @
  axisLabel :: LensLike' f a (AxisLabel b (V a) (N a))

  -- | The text to use when labeling the axis.
  axisLabelText :: Functor f => LensLike' f a String
  axisLabelText = LensLike' f a (AxisLabel b (V a) (N a))
forall (f :: * -> *) a b.
HasAxisLabel f a b =>
LensLike' f a (AxisLabel b (V a) (N a))
axisLabel LensLike' f a (AxisLabel b (V a) (N a))
-> ((String -> f String)
    -> AxisLabel b (V a) (N a) -> f (AxisLabel b (V a) (N a)))
-> LensLike' f a String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AxisLabel b (V a) (N a) -> String)
-> (AxisLabel b (V a) (N a) -> String -> AxisLabel b (V a) (N a))
-> Lens
     (AxisLabel b (V a) (N a)) (AxisLabel b (V a) (N a)) String String
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens AxisLabel b (V a) (N a) -> String
forall b (v :: * -> *) n. AxisLabel b v n -> String
alText (\AxisLabel b (V a) (N a)
al String
txt -> AxisLabel b (V a) (N a)
al {alText :: String
alText = String
txt})

  -- | The 'TextFunction' to render the text of the axis label.
  axisLabelTextFunction :: Functor f => LensLike' f a (TextFunction b (V a) (N a))
  axisLabelTextFunction = LensLike' f a (AxisLabel b (V a) (N a))
forall (f :: * -> *) a b.
HasAxisLabel f a b =>
LensLike' f a (AxisLabel b (V a) (N a))
axisLabel LensLike' f a (AxisLabel b (V a) (N a))
-> ((TextFunction b (V a) (N a) -> f (TextFunction b (V a) (N a)))
    -> AxisLabel b (V a) (N a) -> f (AxisLabel b (V a) (N a)))
-> LensLike' f a (TextFunction b (V a) (N a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AxisLabel b (V a) (N a) -> TextFunction b (V a) (N a))
-> (AxisLabel b (V a) (N a)
    -> TextFunction b (V a) (N a) -> AxisLabel b (V a) (N a))
-> Lens
     (AxisLabel b (V a) (N a))
     (AxisLabel b (V a) (N a))
     (TextFunction b (V a) (N a))
     (TextFunction b (V a) (N a))
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens AxisLabel b (V a) (N a) -> TextFunction b (V a) (N a)
forall b (v :: * -> *) n. AxisLabel b v n -> TextFunction b v n
alFun (\AxisLabel b (V a) (N a)
al TextFunction b (V a) (N a)
f -> AxisLabel b (V a) (N a)
al {alFun :: TextFunction b (V a) (N a)
alFun = TextFunction b (V a) (N a)
f})

  -- | The gap between the axis and the labels, in the direction
  --   corresponding to the 'axisLabelPosition'.
  axisLabelGap :: Functor f => LensLike' f a (N a)
  axisLabelGap = LensLike' f a (AxisLabel b (V a) (N a))
forall (f :: * -> *) a b.
HasAxisLabel f a b =>
LensLike' f a (AxisLabel b (V a) (N a))
axisLabel LensLike' f a (AxisLabel b (V a) (N a))
-> ((N a -> f (N a))
    -> AxisLabel b (V a) (N a) -> f (AxisLabel b (V a) (N a)))
-> LensLike' f a (N a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AxisLabel b (V a) (N a) -> N a)
-> (AxisLabel b (V a) (N a) -> N a -> AxisLabel b (V a) (N a))
-> Lens
     (AxisLabel b (V a) (N a)) (AxisLabel b (V a) (N a)) (N a) (N a)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens AxisLabel b (V a) (N a) -> N a
forall b (v :: * -> *) n. AxisLabel b v n -> n
alGap (\AxisLabel b (V a) (N a)
al N a
sty -> AxisLabel b (V a) (N a)
al {alGap :: N a
alGap = N a
sty})

  -- | The 'Style' to use on the rendered text.
  axisLabelStyle :: Functor f => LensLike' f a (Style (V a) (N a))
  axisLabelStyle = LensLike' f a (AxisLabel b (V a) (N a))
forall (f :: * -> *) a b.
HasAxisLabel f a b =>
LensLike' f a (AxisLabel b (V a) (N a))
axisLabel LensLike' f a (AxisLabel b (V a) (N a))
-> ((Style (V a) (N a) -> f (Style (V a) (N a)))
    -> AxisLabel b (V a) (N a) -> f (AxisLabel b (V a) (N a)))
-> LensLike' f a (Style (V a) (N a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AxisLabel b (V a) (N a) -> Style (V a) (N a))
-> (AxisLabel b (V a) (N a)
    -> Style (V a) (N a) -> AxisLabel b (V a) (N a))
-> Lens
     (AxisLabel b (V a) (N a))
     (AxisLabel b (V a) (N a))
     (Style (V a) (N a))
     (Style (V a) (N a))
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens AxisLabel b (V a) (N a) -> Style (V a) (N a)
forall b (v :: * -> *) n. AxisLabel b v n -> Style v n
alStyle (\AxisLabel b (V a) (N a)
al Style (V a) (N a)
sty -> AxisLabel b (V a) (N a)
al {alStyle :: Style (V a) (N a)
alStyle = Style (V a) (N a)
sty})

  -- | The position the label will be placed parallel to the axis.
  axisLabelPosition :: Functor f => LensLike' f a AxisLabelPosition
  axisLabelPosition = LensLike' f a (AxisLabel b (V a) (N a))
forall (f :: * -> *) a b.
HasAxisLabel f a b =>
LensLike' f a (AxisLabel b (V a) (N a))
axisLabel LensLike' f a (AxisLabel b (V a) (N a))
-> ((AxisLabelPosition -> f AxisLabelPosition)
    -> AxisLabel b (V a) (N a) -> f (AxisLabel b (V a) (N a)))
-> LensLike' f a AxisLabelPosition
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AxisLabel b (V a) (N a) -> AxisLabelPosition)
-> (AxisLabel b (V a) (N a)
    -> AxisLabelPosition -> AxisLabel b (V a) (N a))
-> Lens
     (AxisLabel b (V a) (N a))
     (AxisLabel b (V a) (N a))
     AxisLabelPosition
     AxisLabelPosition
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens AxisLabel b (V a) (N a) -> AxisLabelPosition
forall b (v :: * -> *) n. AxisLabel b v n -> AxisLabelPosition
alPos (\AxisLabel b (V a) (N a)
al AxisLabelPosition
sty -> AxisLabel b (V a) (N a)
al {alPos :: AxisLabelPosition
alPos = AxisLabelPosition
sty})

  -- | Whether the axis label should be placed inside or outside the
  --   axis.
  axisLabelPlacement :: Functor f => LensLike' f a AxisLabelPosition
  axisLabelPlacement = LensLike' f a (AxisLabel b (V a) (N a))
forall (f :: * -> *) a b.
HasAxisLabel f a b =>
LensLike' f a (AxisLabel b (V a) (N a))
axisLabel LensLike' f a (AxisLabel b (V a) (N a))
-> ((AxisLabelPosition -> f AxisLabelPosition)
    -> AxisLabel b (V a) (N a) -> f (AxisLabel b (V a) (N a)))
-> LensLike' f a AxisLabelPosition
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AxisLabel b (V a) (N a) -> AxisLabelPosition)
-> (AxisLabel b (V a) (N a)
    -> AxisLabelPosition -> AxisLabel b (V a) (N a))
-> Lens
     (AxisLabel b (V a) (N a))
     (AxisLabel b (V a) (N a))
     AxisLabelPosition
     AxisLabelPosition
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens AxisLabel b (V a) (N a) -> AxisLabelPosition
forall b (v :: * -> *) n. AxisLabel b v n -> AxisLabelPosition
alPos (\AxisLabel b (V a) (N a)
al AxisLabelPosition
sty -> AxisLabel b (V a) (N a)
al {alPos :: AxisLabelPosition
alPos = AxisLabelPosition
sty})

instance HasAxisLabel f (AxisLabel b v n) b where
  axisLabel :: LensLike'
  f
  (AxisLabel b v n)
  (AxisLabel b (V (AxisLabel b v n)) (N (AxisLabel b v n)))
axisLabel = LensLike'
  f
  (AxisLabel b v n)
  (AxisLabel b (V (AxisLabel b v n)) (N (AxisLabel b v n)))
forall a. a -> a
id

instance Typeable n => HasStyle (AxisLabel b v n) where
  applyStyle :: Style (V (AxisLabel b v n)) (N (AxisLabel b v n))
-> AxisLabel b v n -> AxisLabel b v n
applyStyle = ASetter (AxisLabel b v n) (AxisLabel b v n) (Style v n) (Style v n)
-> (Style v n -> Style v n) -> AxisLabel b v n -> AxisLabel b v n
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter (AxisLabel b v n) (AxisLabel b v n) (Style v n) (Style v n)
forall (f :: * -> *) a b.
(HasAxisLabel f a b, Functor f) =>
LensLike' f a (Style (V a) (N a))
axisLabelStyle ((Style v n -> Style v n) -> AxisLabel b v n -> AxisLabel b v n)
-> (Style v n -> Style v n -> Style v n)
-> Style v n
-> AxisLabel b v n
-> AxisLabel b v n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Style v n -> Style v n -> Style v n
forall a. HasStyle a => Style (V a) (N a) -> a -> a
applyStyle

instance HasVisibility (AxisLabel b v n) where
  visible :: Lens' (AxisLabel b v n) Bool
visible = (AxisLabel b v n -> Bool)
-> (AxisLabel b v n -> Bool -> AxisLabel b v n)
-> Lens' (AxisLabel b v n) Bool
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens AxisLabel b v n -> Bool
forall b (v :: * -> *) n. AxisLabel b v n -> Bool
alVisible (\AxisLabel b v n
al Bool
b -> AxisLabel b v n
al {alVisible :: Bool
alVisible = Bool
b})

instance HasGap (AxisLabel b v n) where
  gap :: Lens' (AxisLabel b v n) (N (AxisLabel b v n))
gap = LensLike' f (AxisLabel b v n) (N (AxisLabel b v n))
forall (f :: * -> *) a b.
(HasAxisLabel f a b, Functor f) =>
LensLike' f a (N a)
axisLabelGap

instance (TypeableFloat n, Renderable (Text n) b)
    => Default (AxisLabel b V2 n) where
  def :: AxisLabel b V2 n
def = AxisLabel
    { alFun :: TextFunction b V2 n
alFun       = TextFunction b V2 n
forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
TextAlignment n -> String -> QDiagram b V2 n Any
mkText
    , alText :: String
alText      = String
""
    , alStyle :: Style V2 n
alStyle     = Style V2 n
forall a. Monoid a => a
mempty Style V2 n -> (Style V2 n -> Style V2 n) -> Style V2 n
forall a b. a -> (a -> b) -> b
& Measure n -> Style V2 n -> Style V2 n
forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
Measure n -> a -> a
fontSize (n -> Measure n
forall n. n -> Measure n
output n
11)
                           Style V2 n -> (Style V2 n -> Style V2 n) -> Style V2 n
forall a b. a -> (a -> b) -> b
& Colour Double -> Style V2 n -> Style V2 n
forall n a c.
(InSpace V2 n a, Color c, Typeable n, Floating n, HasStyle a) =>
c -> a -> a
recommendFillColor Colour Double
forall a. Num a => Colour a
black
    , alGap :: n
alGap       = n
30
    , alPos :: AxisLabelPosition
alPos       = AxisLabelPosition
MiddleAxisLabel
    , alPlacement :: AxisLabelPlacement
alPlacement = AxisLabelPlacement
OutsideAxisLabel
    , alVisible :: Bool
alVisible   = Bool
True
    }

------------------------------------------------------------------------
-- Tick labels
------------------------------------------------------------------------

-- | 'TickLabels' describes how to draw the labels next to ticks. See
--   'HasTickLabels' for more options.
data TickLabels b v n = TickLabels
  { forall b (v :: * -> *) n.
TickLabels b v n -> [n] -> (n, n) -> [(n, String)]
tlFun     :: [n] -> (n,n) -> [(n, String)]
  , forall b (v :: * -> *) n. TickLabels b v n -> TextFunction b v n
tlTextFun :: TextFunction b v n
  , forall b (v :: * -> *) n. TickLabels b v n -> Style v n
tlStyle   :: Style v n
  , forall b (v :: * -> *) n. TickLabels b v n -> n
tlGap     :: n
  , forall b (v :: * -> *) n. TickLabels b v n -> Bool
tlVisible :: Bool
  } deriving Typeable

type instance V (TickLabels b v n) = v
type instance N (TickLabels b v n) = n

class HasTickLabels f a b | a -> b where
  -- | The options for the label of ticks. This can be used on various
  --   levels of the axis:
  --
  -- @
  -- 'tickLabel' :: 'Traversal'' ('Tick' b c n)       ('TickLabels' ('BaseSpace' c) n)
  -- 'tickLabel' :: 'Lens''      ('SingleAxis' b v n) ('TickLabels' v n)
  -- 'tickLabel' :: 'Lens''      ('TickLabel' v n)    ('TickLabels' v n)
  -- @
  tickLabel :: LensLike' f a (TickLabels b (V a) (N a))

  -- | The 'TextFunction' to render the text.
  --
  --   'Default' is 'mkText'.
  tickLabelTextFunction :: Functor f => LensLike' f a (TextFunction b (V a) (N a))
  tickLabelTextFunction = LensLike' f a (TickLabels b (V a) (N a))
forall (f :: * -> *) a b.
HasTickLabels f a b =>
LensLike' f a (TickLabels b (V a) (N a))
tickLabel LensLike' f a (TickLabels b (V a) (N a))
-> ((TextFunction b (V a) (N a) -> f (TextFunction b (V a) (N a)))
    -> TickLabels b (V a) (N a) -> f (TickLabels b (V a) (N a)))
-> LensLike' f a (TextFunction b (V a) (N a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TickLabels b (V a) (N a) -> TextFunction b (V a) (N a))
-> (TickLabels b (V a) (N a)
    -> TextFunction b (V a) (N a) -> TickLabels b (V a) (N a))
-> Lens
     (TickLabels b (V a) (N a))
     (TickLabels b (V a) (N a))
     (TextFunction b (V a) (N a))
     (TextFunction b (V a) (N a))
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens TickLabels b (V a) (N a) -> TextFunction b (V a) (N a)
forall b (v :: * -> *) n. TickLabels b v n -> TextFunction b v n
tlTextFun (\TickLabels b (V a) (N a)
tl TextFunction b (V a) (N a)
f -> TickLabels b (V a) (N a)
tl {tlTextFun :: TextFunction b (V a) (N a)
tlTextFun = TextFunction b (V a) (N a)
f})

  -- | Tick labels functions are used to draw the tick labels. They have
  --   access to the major ticks and the current bounds. Returns the
  --   position of the tick and label to use at that position.
  --
  --   'Default' is @'atMajorTicks' 'floatShow'@
  tickLabelFunction :: Functor f => LensLike' f a ([N a] -> (N a, N a) -> [(N a, String)])
  tickLabelFunction = LensLike' f a (TickLabels b (V a) (N a))
forall (f :: * -> *) a b.
HasTickLabels f a b =>
LensLike' f a (TickLabels b (V a) (N a))
tickLabel LensLike' f a (TickLabels b (V a) (N a))
-> ((([N a] -> (N a, N a) -> [(N a, String)])
     -> f ([N a] -> (N a, N a) -> [(N a, String)]))
    -> TickLabels b (V a) (N a) -> f (TickLabels b (V a) (N a)))
-> LensLike' f a ([N a] -> (N a, N a) -> [(N a, String)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TickLabels b (V a) (N a)
 -> [N a] -> (N a, N a) -> [(N a, String)])
-> (TickLabels b (V a) (N a)
    -> ([N a] -> (N a, N a) -> [(N a, String)])
    -> TickLabels b (V a) (N a))
-> Lens
     (TickLabels b (V a) (N a))
     (TickLabels b (V a) (N a))
     ([N a] -> (N a, N a) -> [(N a, String)])
     ([N a] -> (N a, N a) -> [(N a, String)])
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens TickLabels b (V a) (N a) -> [N a] -> (N a, N a) -> [(N a, String)]
forall b (v :: * -> *) n.
TickLabels b v n -> [n] -> (n, n) -> [(n, String)]
tlFun (\TickLabels b (V a) (N a)
tl [N a] -> (N a, N a) -> [(N a, String)]
f -> TickLabels b (V a) (N a)
tl {tlFun :: [N a] -> (N a, N a) -> [(N a, String)]
tlFun = [N a] -> (N a, N a) -> [(N a, String)]
f})

  -- | The 'Style' to use on the rendered text.
  --
  --   'Default' is @'fontSize' ('output' 11)@.
  tickLabelStyle :: Functor f => LensLike' f a (Style (V a) (N a))
  tickLabelStyle = LensLike' f a (TickLabels b (V a) (N a))
forall (f :: * -> *) a b.
HasTickLabels f a b =>
LensLike' f a (TickLabels b (V a) (N a))
tickLabel LensLike' f a (TickLabels b (V a) (N a))
-> ((Style (V a) (N a) -> f (Style (V a) (N a)))
    -> TickLabels b (V a) (N a) -> f (TickLabels b (V a) (N a)))
-> LensLike' f a (Style (V a) (N a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TickLabels b (V a) (N a) -> Style (V a) (N a))
-> (TickLabels b (V a) (N a)
    -> Style (V a) (N a) -> TickLabels b (V a) (N a))
-> Lens
     (TickLabels b (V a) (N a))
     (TickLabels b (V a) (N a))
     (Style (V a) (N a))
     (Style (V a) (N a))
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens TickLabels b (V a) (N a) -> Style (V a) (N a)
forall b (v :: * -> *) n. TickLabels b v n -> Style v n
tlStyle (\TickLabels b (V a) (N a)
tl Style (V a) (N a)
sty -> TickLabels b (V a) (N a)
tl {tlStyle :: Style (V a) (N a)
tlStyle = Style (V a) (N a)
sty})

  -- | The gap between the axis and the tick labels.
  --
  --   'Default' is @12@.
  tickLabelGap :: Functor f => LensLike' f a (N a)
  tickLabelGap = LensLike' f a (TickLabels b (V a) (N a))
forall (f :: * -> *) a b.
HasTickLabels f a b =>
LensLike' f a (TickLabels b (V a) (N a))
tickLabel LensLike' f a (TickLabels b (V a) (N a))
-> ((N a -> f (N a))
    -> TickLabels b (V a) (N a) -> f (TickLabels b (V a) (N a)))
-> LensLike' f a (N a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TickLabels b (V a) (N a) -> N a)
-> (TickLabels b (V a) (N a) -> N a -> TickLabels b (V a) (N a))
-> Lens
     (TickLabels b (V a) (N a)) (TickLabels b (V a) (N a)) (N a) (N a)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens TickLabels b (V a) (N a) -> N a
forall b (v :: * -> *) n. TickLabels b v n -> n
tlGap (\TickLabels b (V a) (N a)
tl N a
n -> TickLabels b (V a) (N a)
tl {tlGap :: N a
tlGap = N a
n})

instance HasTickLabels f (TickLabels b v n) b where
  tickLabel :: LensLike'
  f
  (TickLabels b v n)
  (TickLabels b (V (TickLabels b v n)) (N (TickLabels b v n)))
tickLabel = LensLike'
  f
  (TickLabels b v n)
  (TickLabels b (V (TickLabels b v n)) (N (TickLabels b v n)))
forall a. a -> a
id

instance HasGap (TickLabels b v n) where
  gap :: Lens' (TickLabels b v n) (N (TickLabels b v n))
gap = LensLike' f (TickLabels b v n) (N (TickLabels b v n))
forall (f :: * -> *) a b.
(HasTickLabels f a b, Functor f) =>
LensLike' f a (N a)
tickLabelGap

instance (TypeableFloat n, Renderable (Text n) b)
    => Default (TickLabels b V2 n) where
  def :: TickLabels b V2 n
def = TickLabels
    { tlFun :: [n] -> (n, n) -> [(n, String)]
tlFun     = (n -> String) -> [n] -> (n, n) -> [(n, String)]
forall n. (n -> String) -> [n] -> (n, n) -> [(n, String)]
atMajorTicks n -> String
forall n. Real n => n -> String
floatShow
    , tlTextFun :: TextFunction b V2 n
tlTextFun = TextFunction b V2 n
forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
TextAlignment n -> String -> QDiagram b V2 n Any
mkText
    , tlStyle :: Style V2 n
tlStyle   = Style V2 n
forall a. Monoid a => a
mempty Style V2 n -> (Style V2 n -> Style V2 n) -> Style V2 n
forall a b. a -> (a -> b) -> b
& Measure n -> Style V2 n -> Style V2 n
forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
Measure n -> a -> a
fontSize (n -> Measure n
forall n. n -> Measure n
output n
11)
                         Style V2 n -> (Style V2 n -> Style V2 n) -> Style V2 n
forall a b. a -> (a -> b) -> b
& Colour Double -> Style V2 n -> Style V2 n
forall n a c.
(InSpace V2 n a, Color c, Typeable n, Floating n, HasStyle a) =>
c -> a -> a
recommendFillColor Colour Double
forall a. Num a => Colour a
black
    , tlGap :: n
tlGap     = n
12
    , tlVisible :: Bool
tlVisible = Bool
True
    }

instance HasVisibility (TickLabels b v n) where
  visible :: Lens' (TickLabels b v n) Bool
visible = (TickLabels b v n -> Bool)
-> (TickLabels b v n -> Bool -> TickLabels b v n)
-> Lens' (TickLabels b v n) Bool
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens TickLabels b v n -> Bool
forall b (v :: * -> *) n. TickLabels b v n -> Bool
tlVisible (\TickLabels b v n
tl Bool
b -> TickLabels b v n
tl {tlVisible :: Bool
tlVisible = Bool
b})

-- | Setter over the final positions the major ticks. This is not as
--   general as 'tickLabelFunction' because you don't have access to the
--   bounds but it can be useful when you know exactly what ticks you
--   want to add or modify existing tick positions or to add an extra
--   value:
--
-- @
-- xAxis . tickLabelPositions .= [(1, "apples"), (2, "oranges"), (3, "bananas"]
-- yAxis . tickLabelPositions <>= [(1.5, "critial mass")]
-- @
--
--  If you want to change or add normal ticks see 'majorTicksFunction'.
--
tickLabelPositions
  :: (HasTickLabels f a b, Settable f)
  => LensLike' f a [(N a, String)]
tickLabelPositions :: forall (f :: * -> *) a b.
(HasTickLabels f a b, Settable f) =>
LensLike' f a [(N a, String)]
tickLabelPositions = LensLike' f a ([N a] -> (N a, N a) -> [(N a, String)])
forall (f :: * -> *) a b.
(HasTickLabels f a b, Functor f) =>
LensLike' f a ([N a] -> (N a, N a) -> [(N a, String)])
tickLabelFunction LensLike' f a ([N a] -> (N a, N a) -> [(N a, String)])
-> (([(N a, String)] -> f [(N a, String)])
    -> ([N a] -> (N a, N a) -> [(N a, String)])
    -> f ([N a] -> (N a, N a) -> [(N a, String)]))
-> ([(N a, String)] -> f [(N a, String)])
-> a
-> f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((N a, N a) -> [(N a, String)])
 -> f ((N a, N a) -> [(N a, String)]))
-> ([N a] -> (N a, N a) -> [(N a, String)])
-> f ([N a] -> (N a, N a) -> [(N a, String)])
forall (f :: * -> *) a b. Functor f => Setter (f a) (f b) a b
mapped ((((N a, N a) -> [(N a, String)])
  -> f ((N a, N a) -> [(N a, String)]))
 -> ([N a] -> (N a, N a) -> [(N a, String)])
 -> f ([N a] -> (N a, N a) -> [(N a, String)]))
-> (([(N a, String)] -> f [(N a, String)])
    -> ((N a, N a) -> [(N a, String)])
    -> f ((N a, N a) -> [(N a, String)]))
-> ([(N a, String)] -> f [(N a, String)])
-> ([N a] -> (N a, N a) -> [(N a, String)])
-> f ([N a] -> (N a, N a) -> [(N a, String)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([(N a, String)] -> f [(N a, String)])
-> ((N a, N a) -> [(N a, String)])
-> f ((N a, N a) -> [(N a, String)])
forall (f :: * -> *) a b. Functor f => Setter (f a) (f b) a b
mapped

-- | Numbers are shown as 'Float's to reduce the chance of numbers like
--   1.30000000008. (This is not an ideal solution.)
floatShow :: Real n => n -> String
floatShow :: forall n. Real n => n -> String
floatShow = Float -> String
forall a. Show a => a -> String
show (Float -> String) -> (n -> Float) -> n -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall {n}. Real n => n -> Float
forall a b. (Real a, Fractional b) => a -> b
realToFrac :: Real n => n -> Float)

-- | Make a 'TickLabelFunction' by specifying how to draw a single label
--   from a position on the axis.
atMajorTicks :: (n -> String) -> [n] -> (n,n) -> [(n, String)]
atMajorTicks :: forall n. (n -> String) -> [n] -> (n, n) -> [(n, String)]
atMajorTicks n -> String
f [n]
ticks (n, n)
_ = (n -> (n, String)) -> [n] -> [(n, String)]
forall a b. (a -> b) -> [a] -> [b]
map ((,) (n -> String -> (n, String)) -> (n -> String) -> n -> (n, String)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> n -> String
f) [n]
ticks

-- -- | Use the list of strings as the labels for the axis, starting at 1
-- --   and going to 2, 3, 4 ... .
-- stringLabels :: Num n => [(n, String)] -> TickLabelFunction n
-- stringLabels nms _ _ = iover (each . itraversed) (\i l -> (fromIntegral (i + 1), l)) nms