module FPPrac.Trees.GeneralTree where import EventLoop.CommonTypes import EventLoop.Output import FPPrac.Trees.LayoutTree -- Courier 16px textFont = "Courier" textHeight = 16 :: Float -- px charWidth = 10 :: Float marginBetweenTrees = 10 :: Float marginBetweenNodeContent = 2 :: Float marginBetweenNodeRows = 20 :: Float marginBetweenNodeColumns = 20 :: Float data GeneralTree = GeneralTreeBox [GeneralNodeContent] [(GeneralLine, GeneralTree)] deriving (Show) data GeneralNodeContent = GeneralNodeText Color String | GeneralNode Color Radius deriving (Show) data GeneralLine = GeneralLine Color deriving (Show) type Offset = Float type LeftOffset = Offset type TopOffset = Offset type RightOffset = Offset type BottomOffset = Offset type Middle = Float type Height = Float class GeneralizeTree a where generalizeTree :: a -> GeneralTree instance GeneralizeTree GeneralTree where generalizeTree a = a generalNodeDimension :: GeneralTree -> Dimension generalNodeDimension (GeneralTreeBox content _) = flattenDimensions contentDimensions where contentDimensions = map generalNodeContentDimension content flattenDimensions :: [Dimension] -> Dimension flattenDimensions [] = (0.0,0.0) flattenDimensions [d] = d flattenDimensions ((w,h):ds) = (max w wTotal, h + marginBetweenNodeContent + hTotal) where (wTotal, hTotal) = flattenDimensions ds generalNodeContentDimension :: GeneralNodeContent -> Dimension generalNodeContentDimension (GeneralNodeText _ str) = textSize str generalNodeContentDimension (GeneralNode _ rad ) = (2*rad, 2*rad) layoutGeneralTree :: LeftOffset -> TopOffset -> GeneralTree -> (LayoutTree, RightOffset, BottomOffset) layoutGeneralTree leftOffset topOffset box@(GeneralTreeBox content children) = (LBox (x, y) topConnect bottomConnect lcs lchildrenWithLines, rightOffset, bottomOffsetChildren) where x = leftBorder y = topOffset middle = (rightOffset - leftOffset) / 2 + leftOffset rightOffset = max rightOffsetChildren (leftOffset + width) leftBorder = middle - (width / 2) topConnect = (width / 2, 0) bottomConnect = (width / 2, height) (width, height) = generalNodeDimension box lcs = layoutGeneralNodeContentList (width / 2) 0 content (lchildrenWithLines, rightOffsetChildren, bottomOffsetChildren) = layoutGeneralTreeChildren leftOffset (topOffset + marginBetweenNodeRows + height) children layoutGeneralTreeChildren :: LeftOffset -> TopOffset -> [(GeneralLine, GeneralTree)] -> ([(LayoutLine, LayoutTree)], RightOffset, BottomOffset) layoutGeneralTreeChildren left top treesWithLines =(zip lLines lTrees, right, bottom) where lines = map fst treesWithLines generalTrees = map snd treesWithLines lLines = map layoutLine lines (lTrees, right, bottom) = layoutGeneralTrees left top generalTrees layoutLine :: GeneralLine -> LayoutLine layoutLine (GeneralLine color) = LayoutLine color layoutGeneralTrees :: LeftOffset -> TopOffset -> [GeneralTree] -> ([LayoutTree], RightOffset, BottomOffset) layoutGeneralTrees left top [] = ([], left, top) layoutGeneralTrees left top [box] = (\(a,b,c) -> ([a],b,c)) $ layoutGeneralTree left top box layoutGeneralTrees left top (box:bs) = (lbox:lrest, rightRest, max bottom bottomRest) where (lbox, right , bottom) = layoutGeneralTree left top box (lrest, rightRest, bottomRest) = (layoutGeneralTrees (right + marginBetweenNodeColumns) top bs) layoutGeneralNodeContentList :: Middle -> Height -> [GeneralNodeContent] -> [LayoutNodeContent] layoutGeneralNodeContentList _ _ [] = [] layoutGeneralNodeContentList middle height [nc] = [layoutGeneralNodeContent (middle, height) nc] layoutGeneralNodeContentList middle height (nc:ncs) = lnc:(layoutGeneralNodeContentList middle height' ncs) where height' = height + ncHeight + marginBetweenNodeContent (_, ncHeight) = generalNodeContentDimension nc lnc = layoutGeneralNodeContent (middle, height) nc layoutGeneralNodeContent :: Pos -> GeneralNodeContent -> LayoutNodeContent layoutGeneralNodeContent (middle, top) gnc@(GeneralNodeText color str) = LayoutNodeText color (x,y) str (textSize str) where x = middle y = top + h/2 (w, h) = generalNodeContentDimension gnc layoutGeneralNodeContent (middle, top) gnc@(GeneralNode color rad) = LayoutNode color (x,y) rad where x = middle y = top + h/2 (w, h) = generalNodeContentDimension gnc -- (width, height) textSize :: [Char] -> (Float, Float) textSize str = (textWidth, textHeight) where textWidth = charWidth * (fromIntegral (length str)) showTree :: (GeneralizeTree a) => a -> IO () showTree a = showTreeList [a] showTreeList :: (GeneralizeTree a) => [a] -> IO () showTreeList list = outSingle (OutGraphical (Draw (showTreeList' 0 0 0 0 list) "trees")) showTreeList' :: (GeneralizeTree a) => LeftOffset -> TopOffset -> Float -> Int -> [a] -> GObject showTreeList' _ _ _ _ [] = Container [] showTreeList' left top maxBottom i (x:xs) | right <= 1024 = Container (text:gtree:gtrees) | width > 1024 = Container (text:gtree:gtrees) | otherwise = showTreeList' 0 maxBottom' maxBottom' i (x:xs) where maxBottom' = max maxBottom bottom (ltree, right, bottom) = layoutGeneralTree left top (generalizeTree x) gtree = printTree ltree Container gtrees = showTreeList' (right + marginBetweenTrees) top maxBottom' i' xs i' = i + 1 text = treeIndex i (left, top) width = right - left treeIndex :: Int -> Pos -> GObject treeIndex i pos = GObject "treeIndex" (Text (255, 125, 125) 0 (255,75,75) pos 20 "Courier" (show i) False) [] {- Calibri height 16px charWidth :: Char -> Number charWidth c = case c of 'a' -> 7.509259481 'b' -> 7.509259481 'c' -> 7.509259481 'd' -> 7.509259481 'e' -> 7.509259481 'f' -> 5.65740763 'g' -> 8.435185407 'h' -> 7.509259481 'i' -> 3.805555778 'j' -> 5.65740763 'k' -> 7.509259481 'l' -> 3.342592815 'm' -> 12.13888911 'n' -> 7.509259481 'o' -> 7.509259481 'p' -> 7.509259481 'q' -> 7.509259481 'r' -> 5.65740763 's' -> 6.583333556 't' -> 6.583333556 'u' -> 7.509259481 'v' -> 8.435185407 'w' -> 12.13888911 'x' -> 7.509259481 'y' -> 8.435185407 'z' -> 6.583333556 '0' -> 7.509259481 '1' -> 7.509259481 '2' -> 7.509259481 '3' -> 7.509259481 '4' -> 9.361111333 '5' -> 7.509259481 '6' -> 7.509259481 '7' -> 8.435185407 '8' -> 8.435185407 '9' -> 7.509259481 ' ' -> 5.65740763 _ -> 7.509259481 -}