    --------------------------------------------------------------------------------
    -- |
    -- Module      :  Graphics.UI.GLUT.Colormap
    -- Copyright   :  (c) Sven Panne 2002-2013
    -- License     :  BSD3
    --
    -- Maintainer  :  Sven Panne <svenpanne@gmail.com>
    -- Stability   :  stable
    -- Portability :  portable
    --
    -- OpenGL supports both RGBA and color index rendering. The RGBA mode is
    -- generally preferable to color index because more OpenGL rendering
    -- capabilities are available and color index mode requires the loading of
    -- colormap entries.
    --
    -- The GLUT color index state variables are used to read and write entries in a
    -- window\'s color index colormap. Every GLUT color index window has its own
    -- logical color index colormap. The size of a window\'s colormap can be
    -- determined by reading 'numColorMapEntries'.
    --
    -- GLUT color index windows within a program can attempt to share colormap
    -- resources by copying a single color index colormap to multiple windows using
    -- 'copyColormap'. If possible GLUT will attempt to share the actual colormap.
    -- While copying colormaps using 'copyColormap' can potentially allow sharing of
    -- physical colormap resources, logically each window has its own colormap. So
    -- changing a copied colormap of a window will force the duplication of the
    -- colormap. For this reason, color index programs should generally load a
    -- single color index colormap, copy it to all color index windows within the
    -- program, and then not modify any colormap cells.
    --
    -- Use of multiple colormaps is likely to result in colormap installation
    -- problems where some windows are displayed with an incorrect colormap due to
    -- limitations on colormap resources.
    --
    --------------------------------------------------------------------------------

    module Graphics.UI.GLUT.Colormap (
       colorMapEntry,
       copyColormap,
       numColorMapEntries,
       transparentIndex
    ) where

    import Control.Monad.IO.Class ( MonadIO(..) )
    import Data.StateVar ( GettableStateVar, makeGettableStateVar, StateVar, makeStateVar )
    import Foreign.C.Types ( CInt )
    import Graphics.Rendering.OpenGL.GL.VertexSpec ( Index1(..), Color3(..) )
    import Graphics.Rendering.OpenGL.Raw.Types ( GLint, GLfloat )

    import Graphics.UI.GLUT.QueryUtils
    import Graphics.UI.GLUT.Raw
    import Graphics.UI.GLUT.Types

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

    -- | Controls the color index colormap entry of the /current window/\'s logical
    -- colormap for the /layer in use/. The /layer in use/ of the /current window/
    -- should be a color index window. The color index should be zero or greater and
    -- less than the total number of colormap entries for the window (see
    -- 'numColorMapEntries') and different from an overlay\'s transparent index (see
    -- 'transparentIndex').
    --
    -- If the /layer in use/\'s colormap was copied by reference, setting a colormap
    -- entry will force the duplication of the colormap.

    colorMapEntry :: Index1 GLint -> StateVar (Color3 GLfloat)
    colorMapEntry (Index1 cell) =
       makeStateVar (getColorMapEntry (fromIntegral cell))
                    (setColorMapEntry (fromIntegral cell))

    setColorMapEntry :: CInt -> Color3 GLfloat -> IO ()
    setColorMapEntry cell (Color3 r g b) = glutSetColor cell r g b

    getColorMapEntry :: CInt -> IO (Color3 GLfloat)
    getColorMapEntry cell = do
       r <- glutGetColor cell glut_RED
       g <- glutGetColor cell glut_GREEN
       b <- glutGetColor cell glut_BLUE
       return $ Color3 r g b

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

    -- | Copy (lazily if possible to promote sharing) the logical colormap from a
    -- specified window to the /current window/\'s /layer in use/. The copy will be
    -- from the normal plane to the normal plane; or from the overlay to the overlay
    -- (never across different layers). Once a colormap has been copied, avoid
    -- setting cells in the colormap via 'colorMapEntry' since that will force an
    -- actual copy of the colormap if it was previously copied by reference.
    -- 'copyColormap' should only be called when both the /current window/ and the
    -- specified window are color index windows.

    copyColormap :: MonadIO m => Window -> m ()
    copyColormap (Window win) = glutCopyColormap win

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

    -- | Contains the number of entries in the colormap of the /current window/\'s
    -- current layer (0 in RGBA mode).

    numColorMapEntries :: GettableStateVar GLint
    numColorMapEntries =
       makeGettableStateVar $ simpleGet fromIntegral glut_WINDOW_COLORMAP_SIZE

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

    -- | Contains the transparent color index of the overlay of the /current window/
    -- or -1 if no overlay is in use.

    transparentIndex :: GettableStateVar (Index1 GLint)
    transparentIndex =
       makeGettableStateVar $
          layerGet (Index1 . fromIntegral) glut_TRANSPARENT_INDEX