--------------------------------------------------------------------------------
-- |
-- Module      :  Ipe.Matrix
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--
-- Matrix Attributes as defined in Ipe
--
--------------------------------------------------------------------------------
module Ipe.Matrix where

import Control.Lens hiding (rmap)
import HGeometry.Ext
import Ipe.Attributes
import Ipe.Types
import HGeometry.Properties
import HGeometry.Transformation
import Data.Proxy

--------------------------------------------------------------------------------

-- | Takes and Applies the matrix to an ipe object if it has one. Also
-- applies it recursively to any groups.
applyMatrix :: (Fractional r, Eq r) => IpeObject r -> IpeObject r
applyMatrix :: forall r. (Fractional r, Eq r) => IpeObject r -> IpeObject r
applyMatrix = IpeObject r -> IpeObject r
forall r. (Fractional r, Eq r) => IpeObject r -> IpeObject r
applyMatrix' (IpeObject r -> IpeObject r)
-> (IpeObject r -> IpeObject r) -> IpeObject r -> IpeObject r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
  IpeGroup IpeObject' Group r
gr -> IpeObject' Group r -> IpeObject r
forall r. IpeObject' Group r -> IpeObject r
IpeGroup (IpeObject' Group r -> IpeObject r)
-> IpeObject' Group r -> IpeObject r
forall a b. (a -> b) -> a -> b
$ Group r :+ GroupAttributes r
IpeObject' Group r
gr(Group r :+ GroupAttributes r)
-> ((Group r :+ GroupAttributes r) -> IpeObject' Group r)
-> IpeObject' Group r
forall a b. a -> (a -> b) -> b
&(Group r -> Identity (Group r))
-> (Group r :+ GroupAttributes r)
-> Identity (Group r :+ GroupAttributes r)
forall core extra core' (f :: * -> *).
Functor f =>
(core -> f core') -> (core :+ extra) -> f (core' :+ extra)
core((Group r -> Identity (Group r))
 -> (Group r :+ GroupAttributes r)
 -> Identity (Group r :+ GroupAttributes r))
-> ((IpeObject r -> Identity (IpeObject r))
    -> Group r -> Identity (Group r))
-> (IpeObject r -> Identity (IpeObject r))
-> (Group r :+ GroupAttributes r)
-> Identity (Group r :+ GroupAttributes r)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.([IpeObject r] -> Identity [IpeObject r])
-> Group r -> Identity (Group r)
forall r s (f :: * -> *).
Functor f =>
([IpeObject r] -> f [IpeObject s]) -> Group r -> f (Group s)
groupItems(([IpeObject r] -> Identity [IpeObject r])
 -> Group r -> Identity (Group r))
-> ((IpeObject r -> Identity (IpeObject r))
    -> [IpeObject r] -> Identity [IpeObject r])
-> (IpeObject r -> Identity (IpeObject r))
-> Group r
-> Identity (Group r)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(IpeObject r -> Identity (IpeObject r))
-> [IpeObject r] -> Identity [IpeObject r]
Setter [IpeObject r] [IpeObject r] (IpeObject r) (IpeObject r)
forall (f :: * -> *) a b. Functor f => Setter (f a) (f b) a b
mapped ((IpeObject r -> Identity (IpeObject r))
 -> (Group r :+ GroupAttributes r)
 -> Identity (Group r :+ GroupAttributes r))
-> (IpeObject r -> IpeObject r)
-> (Group r :+ GroupAttributes r)
-> Group r :+ GroupAttributes r
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ IpeObject r -> IpeObject r
forall r. (Fractional r, Eq r) => IpeObject r -> IpeObject r
applyMatrix
  IpeObject r
o           -> IpeObject r
o

-- | Take and apply the matrix at this particular object. Does *not*
-- apply it recursively.
applyMatrix'   :: (Fractional r, Eq r) => IpeObject r -> IpeObject r
applyMatrix' :: forall r. (Fractional r, Eq r) => IpeObject r -> IpeObject r
applyMatrix' IpeObject r
o = IpeObject r
-> (Matrix 3 3 r -> IpeObject r)
-> Maybe (Matrix 3 3 r)
-> IpeObject r
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IpeObject r
o Matrix 3 3 r -> IpeObject r
transform (Maybe (Matrix 3 3 r) -> IpeObject r)
-> Maybe (Matrix 3 3 r) -> IpeObject r
forall a b. (a -> b) -> a -> b
$ IpeObject r
oIpeObject r
-> Getting
     (Maybe (Matrix 3 3 r)) (IpeObject r) (Maybe (Matrix 3 3 r))
-> Maybe (Matrix 3 3 r)
forall s a. s -> Getting a s a -> a
^.Getting (Maybe (Matrix 3 3 r)) (IpeObject r) (Maybe (Matrix 3 3 r))
forall c r (f :: * -> *).
HasCommonAttributes c r f =>
Lens' c (f (Matrix 3 3 r))
Lens' (IpeObject r) (Maybe (Matrix 3 3 r))
matrix
  where
    transform :: Matrix 3 3 r -> IpeObject r
transform Matrix 3 3 r
m = (Transformation (Dimension (IpeObject r)) (NumType (IpeObject r))
-> IpeObject r -> IpeObject r
forall g.
IsTransformable g =>
Transformation (Dimension g) (NumType g) -> g -> g
transformBy (Matrix (2 + 1) (2 + 1) r -> Transformation 2 r
forall (d :: Natural) r.
Matrix (d + 1) (d + 1) r -> Transformation d r
Transformation Matrix 3 3 r
Matrix (2 + 1) (2 + 1) r
m) IpeObject r
o)IpeObject r -> (IpeObject r -> IpeObject r) -> IpeObject r
forall a b. a -> (a -> b) -> b
&(Maybe (Matrix 3 3 r) -> Identity (Maybe (Matrix 3 3 r)))
-> IpeObject r -> Identity (IpeObject r)
forall c r (f :: * -> *).
HasCommonAttributes c r f =>
Lens' c (f (Matrix 3 3 r))
Lens' (IpeObject r) (Maybe (Matrix 3 3 r))
matrix ((Maybe (Matrix 3 3 r) -> Identity (Maybe (Matrix 3 3 r)))
 -> IpeObject r -> Identity (IpeObject r))
-> Maybe (Matrix 3 3 r) -> IpeObject r -> IpeObject r
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Maybe (Matrix 3 3 r)
forall a. Maybe a
Nothing

-- | Applies all matrices in the file.
applyMatrices   :: (Fractional r, Eq r) => IpeFile r -> IpeFile r
applyMatrices :: forall r. (Fractional r, Eq r) => IpeFile r -> IpeFile r
applyMatrices IpeFile r
f = IpeFile r
fIpeFile r -> (IpeFile r -> IpeFile r) -> IpeFile r
forall a b. a -> (a -> b) -> b
&(NonEmpty (IpePage r) -> Identity (NonEmpty (IpePage r)))
-> IpeFile r -> Identity (IpeFile r)
forall r r' (f :: * -> *).
Functor f =>
(NonEmpty (IpePage r) -> f (NonEmpty (IpePage r')))
-> IpeFile r -> f (IpeFile r')
pages((NonEmpty (IpePage r) -> Identity (NonEmpty (IpePage r)))
 -> IpeFile r -> Identity (IpeFile r))
-> ((IpePage r -> Identity (IpePage r))
    -> NonEmpty (IpePage r) -> Identity (NonEmpty (IpePage r)))
-> (IpePage r -> Identity (IpePage r))
-> IpeFile r
-> Identity (IpeFile r)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(IpePage r -> Identity (IpePage r))
-> NonEmpty (IpePage r) -> Identity (NonEmpty (IpePage r))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> NonEmpty a -> f (NonEmpty b)
traverse ((IpePage r -> Identity (IpePage r))
 -> IpeFile r -> Identity (IpeFile r))
-> (IpePage r -> IpePage r) -> IpeFile r -> IpeFile r
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ IpePage r -> IpePage r
forall r. (Fractional r, Eq r) => IpePage r -> IpePage r
applyMatricesPage

-- | Applies all Matrices on a given page.
applyMatricesPage   :: (Fractional r, Eq r) => IpePage r -> IpePage r
applyMatricesPage :: forall r. (Fractional r, Eq r) => IpePage r -> IpePage r
applyMatricesPage IpePage r
p = IpePage r
pIpePage r -> (IpePage r -> IpePage r) -> IpePage r
forall a b. a -> (a -> b) -> b
&([IpeObject r] -> Identity [IpeObject r])
-> IpePage r -> Identity (IpePage r)
forall r r' (f :: * -> *).
Functor f =>
([IpeObject r] -> f [IpeObject r']) -> IpePage r -> f (IpePage r')
content(([IpeObject r] -> Identity [IpeObject r])
 -> IpePage r -> Identity (IpePage r))
-> ((IpeObject r -> Identity (IpeObject r))
    -> [IpeObject r] -> Identity [IpeObject r])
-> (IpeObject r -> Identity (IpeObject r))
-> IpePage r
-> Identity (IpePage r)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(IpeObject r -> Identity (IpeObject r))
-> [IpeObject r] -> Identity [IpeObject r]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse ((IpeObject r -> Identity (IpeObject r))
 -> IpePage r -> Identity (IpePage r))
-> (IpeObject r -> IpeObject r) -> IpePage r -> IpePage r
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ IpeObject r -> IpeObject r
forall r. (Fractional r, Eq r) => IpeObject r -> IpeObject r
applyMatrix