    -- -*-haskell-*-
    --  class of flag types
    --
    --  Author : Duncan Coutts
    --
    --  Created: 21 January 2005
    --
    --  Copyright (C) 2001-2005 Duncan Coutts, Axel Simon
    --
    --  This library is free software; you can redistribute it and/or
    --  modify it under the terms of the GNU Lesser General Public
    --  License as published by the Free Software Foundation; either
    --  version 2.1 of the License, or (at your option) any later version.
    --
    --  This library is distributed in the hope that it will be useful,
    --  but WITHOUT ANY WARRANTY; without even the implied warranty of
    --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    --  Lesser General Public License for more details.
    --
    -- |
    -- Maintainer  : gtk2hs-users@lists.sourceforge.net
    -- Stability   : provisional
    -- Portability : portable
    --
    -- This module defines a type class for flags that are marshaled as bitflags.
    --
    module System.Glib.Flags (
      Flags,
      fromFlags,
      toFlags
      ) where

    import Data.Bits ((.|.), (.&.), testBit, shiftL, shiftR)
    import Data.Maybe (catMaybes)

    class  (Enum a, Bounded a) => Flags a

    fromFlags :: Flags a => [a] -> Int
    fromFlags :: [a] -> Int
    fromFlags is :: [a]
    is = Int -> [a] -> Int
    forall a. Enum a => Int -> [a] -> Int
    orNum 0 [a]
    is
      where orNum :: Int -> [a] -> Int
    orNum n :: Int
    n []     = Int
    n
            orNum n :: Int
    n (i :: a
    i:is :: [a]
    is) = Int -> [a] -> Int
    orNum (Int
    n Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. a -> Int
    forall a. Enum a => a -> Int
    fromEnum a
    i) [a]
    is

    -- * Note that this function ignores bits set in the passed
    --   'Int' that do not correspond to a flag.
    toFlags :: Flags a => Int -> [a]
    toFlags :: Int -> [a]
    toFlags n :: Int
    n = [Maybe a] -> [a]
    forall a. [Maybe a] -> [a]
    catMaybes [ if Int
    n Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .&. a -> Int
    forall a. Enum a => a -> Int
    fromEnum a
    flag Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == a -> Int
    forall a. Enum a => a -> Int
    fromEnum a
    flag
                               then a -> Maybe a
    forall a. a -> Maybe a
    Just a
    flag
                               else Maybe a
    forall a. Maybe a
    Nothing
                          | a
    flag <- [a
    forall a. Bounded a => a
    minBound .. a
    forall a. Bounded a => a
    maxBound] ]

    -------------------------
    -- QuickCheck test code

    {-
    import Test.QuickCheck
    import List (sort, nub)
    -- to run these tests you must copy EventMask and its Enum instance here
    -- and make it an instance of Ord, Eq and Show.

    prop_ToFlagsFromFlags :: Int -> Property
    prop_ToFlagsFromFlags n =
      (n >= 1 && n <= 21)
      ==>
      collect n $
      let flag :: [EventMask]
          flag = toFlags (2^n)
       in 2^n == fromFlags flag

    prop_FromFlagsToFlags :: [EventMask] -> Bool
    prop_FromFlagsToFlags flags =
      (nub . sort) flags == toFlags (fromFlags flags)

    instance Arbitrary EventMask where
      arbitrary     = sized $ \_ -> do x <- choose (1,21 :: Int)
                                       return (toEnum $ 2^x)
    -}