glib-0.13.0.6: System/Glib/Attributes.hs
{-# LANGUAGE ExistentialQuantification #-}
-- -*-haskell-*-
-- GIMP Toolkit (GTK) Attributes interface
--
-- Author : Duncan Coutts
--
-- Created: 21 January 2005
--
-- Copyright (C) 2005 Duncan Coutts
--
-- Partially derived from the hs-fltk and wxHaskell projects which
-- are both under LGPL compatible licenses.
--
-- 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 : experimental
-- Portability : portable
--
-- Attributes interface
--
-- Attributes of an object can be get and set. Getting the value of an
-- object's attribute is straingtforward. As an example consider a @button@
-- widget and an attribute called @buttonLabel@.
--
-- > value <- get button buttonLabel
--
-- The syntax for setting or updating an attribute is only slightly more
-- complex. At the simplest level it is just:
--
-- > set button [ buttonLabel := value ]
--
-- However as the list notation would indicate, you can set or update multiple
-- attributes of the same object in one go:
--
-- > set button [ buttonLabel := value, buttonFocusOnClick := False ]
--
-- You are not limited to setting the value of an attribute, you can also
-- apply an update function to an attribute's value. That is the function
-- receives the current value of the attribute and returns the new value.
--
-- > set spinButton [ spinButtonValue :~ (+1) ]
--
-- There are other variants of these operators, (see 'AttrOp'). ':=>' and
-- ':~>' and like ':=' and ':~' but operate in the 'IO' monad rather
-- than being pure. There is also '::=' and '::~' which take the object
-- as an extra parameter.
--
-- Attributes can be read only, write only or both read\/write.
--
module System.Glib.Attributes (
-- * Attribute types
Attr,
ReadAttr,
WriteAttr,
ReadWriteAttr,
-- * Interface for getting, setting and updating attributes
AttrOp(..),
get,
set,
-- * Internal attribute constructors
newNamedAttr,
readNamedAttr,
writeNamedAttr,
newAttr,
readAttr,
writeAttr,
) where
infixr 0 :=,:~,:=>,:~>,::=,::~
-- | An ordinary attribute. Most attributes have the same get and set types.
type Attr o a = ReadWriteAttr o a a
-- | A read-only attribute.
type ReadAttr o a = ReadWriteAttr o a ()
-- | A write-only attribute.
type WriteAttr o b = ReadWriteAttr o () b
-- | A generalised attribute with independent get and set types.
data ReadWriteAttr o a b = Attr String !(o -> IO a) !(o -> b -> IO ())
instance Show (ReadWriteAttr o a b) where
show (Attr str _ _) = str
-- | Create a new attribute with a getter and setter function.
newNamedAttr :: String -> (o -> IO a) -> (o -> b -> IO ()) -> ReadWriteAttr o a b
newNamedAttr prop getter setter = Attr prop getter setter
-- | Create a new read-only attribute.
readNamedAttr :: String -> (o -> IO a) -> ReadAttr o a
readNamedAttr prop getter = Attr prop getter (\_ _ -> return ())
-- | Create a new write-only attribute.
writeNamedAttr :: String -> (o -> b -> IO ()) -> WriteAttr o b
writeNamedAttr prop setter = Attr prop (\_ -> return ()) setter
-- | Create a new attribute with a getter and setter function.
newAttr :: (o -> IO a) -> (o -> b -> IO ()) -> ReadWriteAttr o a b
newAttr getter setter = Attr "unnamed attribute" getter setter
-- | Create a new read-only attribute.
readAttr :: (o -> IO a) -> ReadAttr o a
readAttr getter = Attr "unnamed attribute" getter (\_ _ -> return ())
-- | Create a new write-only attribute.
writeAttr :: (o -> b -> IO ()) -> WriteAttr o b
writeAttr setter = Attr "unnamed attribute" (\_ -> return ()) setter
-- | A set or update operation on an attribute.
data AttrOp o
= forall a b.
ReadWriteAttr o a b := b -- ^ Assign a value to an
-- attribute.
| forall a b.
ReadWriteAttr o a b :~ ( a -> b) -- ^ Apply an update function to
-- an attribute.
| forall a b.
ReadWriteAttr o a b :=> ( IO b) -- ^ Assign the result of an IO
-- action to an attribute.
| forall a b.
ReadWriteAttr o a b :~> ( a -> IO b) -- ^ Apply a IO update function
-- to an attribute.
| forall a b.
ReadWriteAttr o a b ::= (o -> b) -- ^ Assign a value to an
-- attribute with the object as
-- an argument.
| forall a b.
ReadWriteAttr o a b ::~ (o -> a -> b) -- ^ Apply an update function to
-- an attribute with the object
-- as an argument.
-- | Set a number of properties for some object.
set :: o -> [AttrOp o] -> IO ()
set obj = mapM_ app
where
app (Attr _ getter setter := x) = setter obj x
app (Attr _ getter setter :~ f) = getter obj >>= \v -> setter obj (f v)
app (Attr _ getter setter :=> x) = x >>= setter obj
app (Attr _ getter setter :~> f) = getter obj >>= f >>= setter obj
app (Attr _ getter setter ::= f) = setter obj (f obj)
app (Attr _ getter setter ::~ f) = getter obj >>= \v -> setter obj (f obj v)
-- | Get an Attr of an object.
get :: o -> ReadWriteAttr o a b -> IO a
get o (Attr _ getter setter) = getter o