module DrawingOps where
import Drawing(Drawing(..),DPath(..),up)
import Utils(number)
drawingPart drawing path =
case maybeDrawingPart drawing path of
Just part -> part
Nothing -> error ("bad path in drawingPart "++show path)
maybeDrawingPart drawing path =
case (path::DPath) of
[] -> Just drawing
p:ps -> part drawing
where
part0 d = if p==0
then maybeDrawingPart d ps
else Nothing
part drawing =
case drawing of
AtomicD _ -> Nothing
LabelD _ d -> part0 d
AttribD gcattrs d -> part0 d
SpacedD spacer d -> part0 d
PlacedD placer d -> part0 d
ComposedD _ ds ->
if 1<=p && p<=length ds
then maybeDrawingPart (ds !! (p-1)) ps
else Nothing
drawingAnnotPart = drawingAnnotPart' (const True)
drawingAnnotPart' p drawing path =
case path of
[] -> []
_ -> case maybeDrawingPart drawing path of
Just (LabelD a _) | p a -> path
_ -> drawingAnnotPart' p drawing (up path)
isVisibleDrawingPart drawing path =
case (path::DPath) of
[] -> True
p:ps -> visible drawing
where
visible0 d = p==0 && isVisibleDrawingPart d ps -- ??
visible drawing =
case drawing of
AtomicD _ -> True -- ??
LabelD _ d -> visible0 d
AttribD gcattrs d -> visible0 d
SpacedD spacer d -> visible0 d
PlacedD placer d -> visible0 d
ComposedD n ds ->
1<=p && p<=n && isVisibleDrawingPart (ds !! (p-1)) ps
visibleAncestor drawing path =
case path::DPath of
[] -> path
p:ps ->
case drawing of
AtomicD _ -> path
LabelD _ d -> skip d
AttribD gcattrs d -> skip d
SpacedD spacer d -> skip d
PlacedD placer d -> skip d
ComposedD n ds ->
if 1<=p && p<=n
then p:visibleAncestor (ds!!(p-1)) ps
else []
where skip d = 0:visibleAncestor d ps
replacePart drawing path new = updatePart drawing path (const new)
updatePart drawing path new =
case (path::DPath) of
[] -> new drawing
p:ps -> repl drawing
where
err = error "bad path in updatePart"
repl0 d = if p==0 then updatePart d ps new else err
repl drawing =
case drawing of
AtomicD _ -> err
AttribD gcattrs d -> AttribD gcattrs (repl0 d)
LabelD label d -> LabelD label (repl0 d)
SpacedD spacer d -> SpacedD spacer (repl0 d)
PlacedD placer d -> PlacedD placer (repl0 d)
ComposedD n ds ->
let (pre,d:post) = splitAt (p-1) ds
in ComposedD n (pre++updatePart d ps new:post)
mapLabelDrawing f = ma
where
ma d =
case d of
AtomicD x -> AtomicD x
AttribD gcattrs d -> AttribD gcattrs (ma d)
LabelD label d -> LabelD (f label) (ma d)
SpacedD spacer d -> SpacedD spacer (ma d)
PlacedD placer d -> PlacedD placer (ma d)
ComposedD n ds -> ComposedD n (map ma ds)
mapLeafDrawing f = ma
where
ma d =
case d of
AtomicD x -> AtomicD (f x)
AttribD gcattrs d -> AttribD gcattrs (ma d)
LabelD label d -> LabelD label (ma d)
SpacedD spacer d -> SpacedD spacer (ma d)
PlacedD placer d -> PlacedD placer (ma d)
ComposedD n ds -> ComposedD n (map ma ds)
{-
drawingArity drawing =
case drawing of
AtomicD _ -> 0
LabelD _ d -> drawingArity d
AttribD _ d -> drawingArity d
SpacedD _ d -> drawingArity d
PlacedD _ d -> drawingArity d
ComposedD _ ds -> length ds
-}
annotChildren = annotChildren' (const True)
annotChildren' :: (a -> Bool) -> (Drawing a d) -> [(DPath, Drawing a d)]
annotChildren' p drawing =
case drawing of
LabelD _ d -> ac0 d
d -> ac d
where
ac0 d0 = [(0:p,d)| (p,d)<-ac d0]
ac d =
case d of
AtomicD _ -> []
LabelD a d' -> if p a then [([],d)] else ac0 d'
AttribD _ d -> ac0 d
SpacedD _ d -> ac0 d
PlacedD _ d -> ac0 d
ComposedD _ ds -> [(i:p,d) | (i,cs) <- number 1 (map ac ds), (p,d)<-cs]
{-
drawingAnnots :: Drawing a d -> [(DPath,a)]
drawingAnnots drawing = da drawing
where
da d =
case d of
AtomicD _ -> []
LabelD a d' -> ([],a):da d'
AttribD _ d -> da d
SpacedD _ d -> da d
PlacedD _ d -> da d
ComposedD _ ds -> [(i:p,d) | (i,cs) <- number 1 (map da ds), (p,d)<-cs]
-}
drawingAnnots drawing = extractParts drawing sel
where sel (LabelD a d) = Just a
sel _ = Nothing
extractParts :: Drawing lbl leaf -> (Drawing lbl leaf -> Maybe a) -> [(DPath,a)]
drawing sel = extr drawing
where
extr0 d = [(0:p,d') | (p,d') <- extr d]
extr d =
(case sel d of
Just x -> (([],x):)
_ -> id) $
case d of
AtomicD _ -> []
LabelD a d' -> extr0 d'
AttribD _ d -> extr0 d
SpacedD _ d -> extr0 d
PlacedD _ d -> extr0 d
ComposedD _ ds -> [(i:p,d) | (i,cs) <- number 1 (map extr ds), (p,d)<-cs]
deletePart drawing [] = drawing -- !! error report?
deletePart drawing path =
updatePart drawing (init path) (deleteElem (last path))
where
deleteElem i = di
where di d =
case d of
ComposedD n ds ->
case splitAt (i-1) ds of
(ds1,_:ds2) -> ComposedD n' (ds1++ds2)
_ -> d -- !! error report?
where n' = if i<=n
then n-1
else n
_ -> d -- !! error report?
{-
AtomicD x -> d -- !! error report?
AttribD gcattrs d -> AttribD gcattrs (di d)
LabelD label d -> LabelD label (di d)
SpacedD spacer d -> SpacedD spacer (di d)
PlacedD placer d -> PlacedD placer (di d)
-}
groupParts pos0 len0 drawing =
case drawing of
ComposedD n ds -> ComposedD n1 (ds1++ComposedD n2 ds2:ds3)
where
(ds1,ds2a) = splitAt (pos0-1) ds
(ds2,ds3) = splitAt len0 ds2a
pos = length ds1
len = length ds2
-- keep the same parts visible
(n1,n2) = if n<=pos then (n,0)
else if n<=pos+len
then (pos+1,n-pos)
else (n-len+1,len)
ungroupParts pos drawing =
case drawing of
ComposedD n1 ds ->
case splitAt (pos-1) ds of
(ds1,ComposedD n2 ds2:ds3) -> ComposedD n (ds1++ds2++ds3)
where
-- Can't preserve visibility when some of ds3 was visible
-- but some of ds2 was hidden
n = if n1<=pos then n1
else if n1==pos+1
then pos+n2
else n1-1+length ds2 -- all of ds2 becomes visible!!
_ -> drawing -- hmm!!
_ -> drawing -- hmm!!