<commit_before>-- | The render core defines the basic types and helper functions for a basic
--   UI system.
--
--   The fundamental data type is the 'Renderer', which is declared in a
--   hierarchical fashion.
module UI.Render.Core ( Renderer(..)
                      , Offset
                      , defaultRenderer
                      , updateWindow
                      , HAlign(..)
                      , VAlign(..)
                      , Coord
                      , Dimensions
                      ) where

import Control.Monad
import Graphics.UI.GLUT

-- | Used for specifying the nudge factors during alignment.
--   These values, along with anything else in this library,
--   are always using the following coordinate system:
--
--   @
--      +
--      ^
--      |
--      |
--      |
--      |
--      +---------> +
--    (0,0)
--   @
type Offset = Int

-- | A type used for specifying horizontal alignment.
data HAlign = LeftAlign    !Offset
            | RightAlign   !Offset
            | HCenterAlign !Offset

-- | A type used for specifying vertical alignment.
data VAlign = TopAlign     !Offset
            | BottomAlign  !Offset
            | VCenterAlign !Offset

-- | The (x, y) coordinates of a point on the screen, measured from the bottom,
--   left corner.
type Coord = (Int, Int)

-- | If you were to draw an axis-aligned bounding box around an object,
--   Dimensions would represent the (x, y) lengths of the sides.
type Dimensions = (Int, Int)

-- | A renderable is anything which can be drawn onto the screen.
--   To build one, use renderer and override the necessary arguments.
--
--   > rect = defaultRenderer { draw = drawRectangle
--   >                        , pos = (10, 4)
--   >                        , dims = (50, 50)
--   >                        }
data Renderer = Renderer { render :: IO () -- ^ Draws the object onto the screen. You
                                          --   don't have to worry about positioning,
                                          --   as this is automatically handled using
                                          --   the 'pos' field.

                         , pos :: Coord -- ^ The position of the bottom-left
                                       --   corner of the object, relative
                                       --   to the bottom left corner of the
                                       --   object's parent.

                         , dims :: Dimensions -- ^ The dimensions of the object.

                         -- | The coordinates of the point to rotate around,
                         --   relative to the bottom-left of the object.
                         , rotateAround :: Coord

                         -- | The amount to rotate the object by, in radians.
                         --   Positive values are clockwise.
                         , rotation :: Double

                         -- | An optional vertical alignment for the object,
                         --   relative to its parent. If this is set, the
                         --   y-component of the 'pos' field will be ignored.
                         , vAlign :: Maybe VAlign

                         -- | An optional horizontal alignment for the object,
                         --   relative to its parent. If this is set, the
                         --   x-component of the 'pos' field will be ignored.
                         , hAlign :: Maybe HAlign

                         -- | Any child renderers are listed here. When the UI
                         --   library renders a frame, first the current
                         --   'Renderer's 'render' method is called, then the
                         --   children are rendered on top.
                         , children :: [Renderer]
                         }

-- | The default renderer. Draws absolutely nothing. Overload its fields with:
--
--   > rect = defaultRenderer { draw = (drawRectangle 50 50)
--   >                        , pos = (10, 4)
--   >                        , dims = (50, 50)
--   >                        }
--   
--   See: 'Renderer'
defaultRenderer :: Renderer
defaultRenderer = Renderer { render = return ()
                           , pos = (0, 0)
                           , dims = (0, 0)
                           , rotateAround = (0, 0)
                           , rotation = 0.0
                           , vAlign = Nothing
                           , hAlign = Nothing
                           , children = []
                           }

-- | Returns the position of a renderer, accounting for any alignment that may
--   take place.
absPos :: Dimensions -- ^ The dimensions of the parent object.
       -> Renderer  -- ^ The renderer whose new position we need.
       -> Coord
absPos parentDims r = let x' = case hAlign r of
                                  Nothing                 -> x
                                  Just (LeftAlign off)    -> off
                                  Just (RightAlign off)   -> pdx - dx + off
                                  Just (HCenterAlign off) -> (pdx - dx) `div` 2 + off

                          y' = case vAlign r of
                                  Nothing                 -> y
                                  Just (BottomAlign off)  -> off
                                  Just (TopAlign off)     -> pdy - dy + off
                                  Just (VCenterAlign off) -> (pdy - dy) `div` 2 + off
                       in (x', y')
    where
        (x, y) = pos r
        (dx, dy) = dims r
        (pdx, pdy) = parentDims

rad2deg :: Double -> Double
rad2deg rad = rad * 180 / pi
{-# INLINE rad2deg #-}

-- | Draws the given renderer, and all its children to the provided window.<commit_msg>comments++<commit_after>-- | The render core defines the basic types and helper functions for a basic
--   UI system.
--
--   The fundamental data type is the 'Renderer', which is declared in a
--   hierarchical fashion.
module UI.Render.Core ( Renderer(..)
                      , Offset
                      , defaultRenderer
                      , updateWindow
                      , HAlign(..)
                      , VAlign(..)
                      , Coord
                      , Dimensions
                      ) where

import Control.Monad
import Graphics.UI.GLUT

-- | Used for specifying the nudge factors during alignment.
--   These values, along with anything else in this library,
--   are always using the following coordinate system:
--
--   @
--      +
--      ^
--      |
--      |
--      |
--      |
--      +---------> +
--    (0,0)
--   @
type Offset = Int

-- | A type used for specifying horizontal alignment.
data HAlign = LeftAlign    !Offset
            | RightAlign   !Offset
            | HCenterAlign !Offset

-- | A type used for specifying vertical alignment.
data VAlign = TopAlign     !Offset
            | BottomAlign  !Offset
            | VCenterAlign !Offset

-- | The (x, y) coordinates of a point on the screen, measured from the bottom,
--   left corner.
type Coord = (Int, Int)

-- | If you were to draw an axis-aligned bounding box around an object,
--   Dimensions would represent the (x, y) lengths of the sides.
type Dimensions = (Int, Int)

-- | A renderable is anything which can be drawn onto the screen.
--   To build one, use renderer and override the necessary arguments.
--
--   > rect = defaultRenderer { draw = drawRectangle
--   >                        , pos = (10, 4)
--   >                        , dims = (50, 50)
--   >                        }
data Renderer = Renderer { render :: IO () -- ^ Draws the object onto the screen. You
                                          --   don't have to worry about positioning,
                                          --   as this is automatically handled using
                                          --   the 'pos' field.

                         , pos :: Coord -- ^ The position of the bottom-left
                                       --   corner of the object, relative
                                       --   to the bottom left corner of the
                                       --   object's parent.

                         , dims :: Dimensions -- ^ The dimensions of the object.

                         -- | The coordinates of the point to rotate around,
                         --   relative to the bottom-left of the object.
                         , rotateAround :: Coord

                         -- | The amount to rotate the object by, in radians.
                         --   Positive values are clockwise.
                         , rotation :: Double

                         -- | An optional vertical alignment for the object,
                         --   relative to its parent. If this is set, the
                         --   y-component of the 'pos' field will be ignored.
                         , vAlign :: Maybe VAlign

                         -- | An optional horizontal alignment for the object,
                         --   relative to its parent. If this is set, the
                         --   x-component of the 'pos' field will be ignored.
                         , hAlign :: Maybe HAlign

                         -- | Any child renderers are listed here. When the UI
                         --   library renders a frame, first the current
                         --   'Renderer's 'render' method is called, then the
                         --   children are rendered on top.
                         , children :: [Renderer]
                         }

-- | The default renderer. Draws absolutely nothing. Overload its fields with:
--
--   > rect = defaultRenderer { draw = (drawRectangle 50 50)
--   >                        , pos = (10, 4)
--   >                        , dims = (50, 50)
--   >                        }
--   
--   See: 'Renderer'
defaultRenderer :: Renderer
defaultRenderer = Renderer { render = return ()
                           , pos = (0, 0)
                           , dims = (0, 0)
                           , rotateAround = (0, 0)
                           , rotation = 0.0
                           , vAlign = Nothing
                           , hAlign = Nothing
                           , children = []
                           }

-- | Returns the position of a renderer, accounting for any alignment that may
--   take place.
absPos :: Dimensions -- ^ The dimensions of the parent object.
       -> Renderer  -- ^ The renderer whose new position we need.
       -> Coord
absPos parentDims r = let x' = case hAlign r of
                                  Nothing                 -> x
                                  Just (LeftAlign off)    -> off
                                  Just (RightAlign off)   -> pdx - dx + off
                                  Just (HCenterAlign off) -> (pdx - dx) `div` 2 + off

                          y' = case vAlign r of
                                  Nothing                 -> y
                                  Just (BottomAlign off)  -> off
                                  Just (TopAlign off)     -> pdy - dy + off
                                  Just (VCenterAlign off) -> (pdy - dy) `div` 2 + off
                       in (x', y')
    where
        (x, y) = pos r
        (dx, dy) = dims r
        (pdx, pdy) = parentDims

rad2deg :: Double -> Double
rad2deg rad = rad * 180 / pi
{-# INLINE rad2deg #-}

-- | Draws the given renderer, and all its children to the provided window.
--   This should be called every frame, for every window on the screen.
{'fraction_non_alphanumeric': 0.08583542441810159, 'fraction_numerical': 0.006229990481958986, 'mean_word_length': 1.0181595949013444, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3355547', 'n_tokens_mistral': 2792, 'n_tokens_neox': 2597, 'n_words': 1049}